I'm writing a function which returns the difference between two integer arrays. I'm assuming that that all elements in input arrays are unique and also the input arrays are not sorted. For Example:
Input:
arr1 = [1,2,3,5,4]
arr2 = [1,2,3]
Expected Output: [4,5]
My Output: [1,2,3,4,5] (when first array is larger than second)
When I make the second array larger than first, I get ArrayIndexOutOfBoundsException.
public class Test{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter length of first array");
int ml = sc.nextInt();
System.out.println("Enter length of second array");
int nl = sc.nextInt();
int m[] = new int[ml];
int n[] = new int[nl];
System.out.println("Enter elements of first array");
for(int i=0;i<ml;i++)
{
m[i] = sc.nextInt();
}
System.out.println("Enter elements of second array");
for(int j=0;j<nl;j++)
{
m[j] = sc.nextInt();
}
ArrayList<Integer> arr1 = new ArrayList<Integer>();
for(int i: m){ arr1.add(i);}
ArrayList<Integer> arr2 = new ArrayList<Integer>();
for(int j: n){ arr2.add(j);}
if(ml>nl)
{
arr1.removeAll(arr2);
System.out.println(arr1);
}
else
{
arr2.removeAll(arr1);
System.out.println(arr2);
}
}
}
In the second iteration you should use n[j] = ... instead of m[j] = ...
You should use more descriptive variable names to prevent thing kind of thing from happening.
If it is not a homework that let you practice on array/iterations, you may consider using Set for much simpler logic:
// pseudo-code
Set<Integer> set1 = new HashSet<>(array1);
Set<Integer> set2 = new HashSet<>(array2);
// Using Guava
Set<Integer> diff = Sets.symmetricDifference(set1, set2);
// Java only
Set<Integer> diff1 = new HashSet<>(set1);
diff1.removeAll(set2); // diff1 contains entries in array1 but not 2
Set<Integer> diff2 = new HashSet<>(set2);
diff2.removeAll(set1); // diff2 contains entries in array2 but not 1
Set<Integer> diff = new HashSet<>(set1);
diff.addAll(set2);
// Java only, using stream
return Stream.concat(set1.stream(), set2.stream())
.filter(i -> ! (set1.contains(i) && set2.contains(i)))
.collect(Collectors.toSet());
You can check if element exist in second one if not can add to output array as below:
int[] array1 = new int[] { 1, 2, 3, 4, 5 };
int[] array2 = new int[] { 1, 2, 3 };
List<Integer> output = new ArrayList<>();
for (int i = 0; i < array1.length; i++) {
boolean flag = false;
for (int j = 0; j < array2.length; j++) {
if (array1[i] == array2[j]) {
flag = true;
break;
}
}
if (!flag) {
output.add(array1[i]);
}
}
System.out.println(output);
Related
I can't get this program to work. It's supposed to take an array as input and output a new array with the accumulative sum of the input array. I used a function for this (bottom part).
For example:
Input: 1 2 3 4
Output: 1 3 6 10
Here's my program:
import java.util.Scanner;
public class Accumulate {
public static void main(String[] args) {
int n, sum = 0;
Scanner s = new Scanner(System.in);
System.out.print("Enter the size of the array:");
n = s.nextInt();
int a[] = new int[n];
System.out.println("Enter all the elements:");
for (int i = 0; i < n; i++) {
a[i] = s.nextInt();
}
System.out.println(Arrays.toString(accSum(a)));
s.close();
}
public static int[] accSum(int[] in) {
int[] out = new int[in.length];
int total = 0;
for (int i = 0; i < in.length; i++) {
total += in[i];
out[i] = total;
}
return out;
}
}
Use Arrays.toString() to print an array.
You can't call System.out.println(accSum(a)); directly as that will print the memory address of the array and not the contents. Wrap the call with Arrays.toString(accSum(a)) and it will print the expected output.
PS: The code in your post doesn't compile:
scanner.close(); should be s.close();
accSum() should be static.
Addendum:
So your full code became this:
public static void main(String[] args) {
int n, sum = 0;
Scanner s = new Scanner(System.in);
System.out.print("Enter the size of the array:");
n = s.nextInt();
int a[] = new int[n];
System.out.println("Enter all the elements:");
for (int i = 0; i < n; i++) {
a[i] = s.nextInt();
}
System.out.println(Arrays.toString(accSum(a)));
s.close();
}
public static int[] accSum(int[] in) {
int[] out = new int[in.length];
int total = 0;
for (int i = 0; i < in.length; i++) {
total += in[i];
out[i] = total;
}
return out;
}
You can use Arrays.stream(int[],int,int) method to get the sum of the previous array elements:
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4};
int[] arr2 = accSum(arr1);
System.out.println(Arrays.toString(arr2));
// [1, 3, 6, 10]
}
public static int[] accSum(int[] arr) {
return IntStream
// iterate over the indices of the array
.range(0, arr.length)
// sum of the current element and all previous elements
.map(i -> arr[i] + Arrays.stream(arr, 0, i).sum())
// return an array
.toArray();
}
See also: Modifying a 2D array
I am new to java. I have a problem that, I have two arrays parentArray and subArray:
parentArray has values, {1,4,4,3,6}
subArray has values {4,4,3}
So, the second array or so-called subArray values are included in the first-array the so-called parentArray, with indexes starting from [1,2,3]. My question is how can we return the index value of the first element of subArray which is also part of parentArray.
i.e.
int[] parentArray = new int[]{1,4,4,3,6};
int[] subArray = new int[]{4,4,3};
As subArray's values are in parentArray starting index from [1], I want my program to return 1.
I have tried comparing two arrays and returning the common elements from both arrays. But ahead of that, I can not think any of logic as I am a beginner.
you can use the Collections.indexOfSubList() as follows:
List<Integer> parentArray = Arrays.asList(1,4,4,3,6);
List<Integer> subArray = Arrays.asList(4,4,3);
int index = Collections.indexOfSubList(parentArray , subArray);
// index is 1
if you want to implement for arrays, check out the source from that and modify it a bit:
public static int indexOfSubList(int[] source, int[] target) {
int sourceSize = source.length;
int targetSize = target.length;
int maxCandidate = sourceSize - targetSize;
nextCand:
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
for (int i=0, j=candidate; i<targetSize; i++, j++)
if (!(target[i] == source[j]))
continue nextCand; // Element mismatch, try next cand
return candidate; // All elements of candidate matched target
}
return -1; // No candidate matched the target
}
usage:
int[] parentArray = new int[]{1,1,1,4,4,3,6};
int[] subArray = new int[]{4,4,3};
int index = indexOfSubList(parentArray, subArray);
// index is 3
System.out.println(index);
I've created a method for this. Try below code,
public int checkSubArray(int[] parentArray, int[] subArray) {
int result = -1;
for (int i = 0; i < parentArray.length; i++) {
int[] temp = Arrays.copyOfRange(parentArray, i, (subArray.length + i)); //This will create a temporary sub array
if (Arrays.equals(temp, subArray)) {
System.out.println(i);
result = i;
}
}
return result;
}
Improved Answer
public int checkSubArray(int[] parentArray, int[] subArray) {
int result = -1;
for (int i = 0; i < parentArray.length; i++) {
if (parentArray[i] == subArray[0]) { // Checking if the first value matches
int[] temp = Arrays.copyOfRange(parentArray, i, (subArray.length + i)); // This will create a temporary sub array
if (Arrays.equals(temp, subArray)) {
System.out.println(i);
result = i;
}
}
}
return result;
}
You could also try something like this if your array only contains integers less than 10.
public static void main(String[] args) {
int[] parentArray = new int[]{1, 4, 4, 3, 6};
int[] subArray = new int[]{4, 4, 3};
String s1 = convertToString(parentArray);
String s2 = convertToString(subArray);
System.out.print(s1.indexOf(s2));
}
private static String convertToString(int[] array) {
StringBuilder stringBuilder = new StringBuilder();
for(int num : array){
stringBuilder.append(num);
}
return stringBuilder.toString();
}
Consider a Permutation P of length n .
Let us define an operation on P as follows:
P[i]=P[P[i]]; for every i from 1 to n
for example:
P[n] = {2, 3, 1};
After 1 operation:
P[1] becomes P[P[1]] = P[2]= 3;
P[2] becomes P[P[2]] = P[3]= 1;
P[3] becomes P[P[3]] = P[1]= 2;
So, P becomes [3, 1, 2] ;
You need to find the minimum number of operations to be performed after which P becomes an Identity Permutation.
Output -1 if not possible.
Input 1:
P = [2 , 1];
Output 1:
1
As it will become Identity Permutation after 1 operation only.
Input 2:
P = [2 , 3 , 1];
Output 2:
-1
As Identity Permutation is not possible by the given operation.
I've tried to solve this code as follows, but I'm not getting the right way to solve it.
Java:
import java.util.Scanner;
public class Permutation {
public static void main(String args[]) throws Exception {
Scanner s = new Scanner(System. in );
System.out.println("Enter the number of Test Cases");
int t = s.nextInt();
for (int i = 0; i < t; i++) {
System.out.println("Enter the number n");
int n = s.nextInt();
int[] arr = new int[n + 1];
for (i = 1; i <= n; i++) {
arr[i] = s.nextInt();
}
int count = 0;
int[] arr1 = new int[n + 1];``
arr1 = arr;
do {
for (i = 1; i <= n; i++) {
arr1[i] = arr1[arr1[i]];
}
count++;
}
while ( arr != arr1 );
System.out.println(count);
}
}
}
In this code,I loop until n! tries or when find the permutation.If check is true,then I found and can write the count,if count reaches the n! which means all permutations are done and I couldn't find the identity permutation and I write -1.Loop boundary is like that.Let's look at the algorithm.
I copied orijinal array to another array to don't lose any information.And after each iteration when array is changed,I also kept it.
After arr1[i] = arr[arr[i]];,I sorted the arr1 and check whether sorted arr1 is equal previous arr1 or not,if they are equals then I found the permutation,break the loop make check boolean true and print result,else iterate one more time.
import java.util.Arrays;
import java.util.Scanner;
public class Permutation {
public static void main(String args[] ) throws Exception {
Scanner s = new Scanner(System.in);
System.out.println("Enter the number of Test Cases");
int t = s.nextInt();
for(int i=0;i<t;i++)
{
System.out.println("Enter the number n");
int n = s.nextInt();
int[] arr=new int[n+1];
for(i=1;i<=n;i++){
arr[i]=s.nextInt();
}
int count=0;
int[] arr1=new int[n+1];
arr1 = Arrays.copyOf(arr, arr.length);
boolean check;
do {
for (i = 1; i <= n; i++) {
arr1[i] = arr[arr[i]];
}
arr = Arrays.copyOf(arr1, arr1.length);
count++;
int [] temp = Arrays.copyOf(arr1, arr1.length);
Arrays.sort(arr1);
check = false;
for(int m =1;m<=n;m++){
if(arr1[m]==temp[m])
check = true;
else{
check = false;
break;
}
}
}
while(count<fact(n) && check!=true);
if(count == fact(n))
System.out.println("-1");
else
System.out.println(count);
}
}
public static int fact(int n){
int temp = 1;
for(int i=1;i<=n;i++)
temp*=i;
return temp;
}
}
I have two int arrays
int[] sum=new int[n];
int[] newTime=new int[n];
First: 1 5 3
Second 10 15 13
Arrays.sort(sum);
Prints 1 3 5
What I want is even for the second array to be sorted with the same indexes
of the
first=>second : 10 13 15
I have tried with maps:
SortedMap<Integer, Integer> m = new TreeMap<Integer, Integer>();
for(int i = 0; i < priorities.length; i++){
m.put(sum[i],newTime[i]);
}
It just sorts the first array only,the indexes of the second array don't change.Help is appreciated!
Thank You!
You could do it with java-8 like this for example:
int[] left = new int[] { 1, 5, 3 };
int[] right = new int[] { 10, 15, 13 };
IntStream.range(0, left.length)
.boxed()
.map(x -> new AbstractMap.SimpleEntry<>(left[x], right[x]))
.sorted(Comparator.comparing(SimpleEntry::getKey))
.forEach(System.out::println);
EDIT
to actually get the second array:
Integer[] second = IntStream.range(0, left.length)
.boxed()
.map(x -> new AbstractMap.SimpleEntry<>(left[x], right[x]))
.sorted(Comparator.comparing(SimpleEntry::getKey))
.map(SimpleEntry::getValue)
.toArray(Integer[]::new);
Your TreeMap approach leads to what you need:
SortedMap<Integer, Integer> m = new TreeMap<Integer, Integer>();
for(int i = 0; i < priorities.length; i++){
m.put(sum[i],newTime[i]);
}
// this will print the elements of the second array in the required order
for (Integer i : m.values()) {
System.out.println (i);
}
Of course you can assign the elements back to the original array if you want:
int count = 0;
for (Integer i : m.values()) {
newTime[count] = i;
}
As correctly commented by mlecz, this solution will only work if the first array (sum) has no duplicates.
Here is the solution, which works when there are duplicates in first array.
You keep values from both arrays together, sort them using indices from one array, and make a list, from corresponding indices from second array.
static Integer[] sort(int[] arr1, int[] arr2) {
assert arr1.length == arr2.length;
class Tuple{
int a1;
int a2;
}
List<Tuple> tuples = new ArrayList<>();
for(int i=0;i<arr1.length;i++){
Tuple t = new Tuple();
t.a1=arr1[i];
t.a2=arr2[i];
tuples.add(t);
}
tuples.sort((t1,t2)->Integer.compare(t1.a1,t2.a1));
return (Integer[]) tuples.stream().map(t->t.a2).collect(Collectors.toList()).toArray(new Integer[arr1.length]);
}
You may sort both arrays at the same time, following the reordering of the first array like this :
int[] sum = { 1, 5, 3 };
int[] newTime = { 10, 15, 13 };
for (int i = 0; i < sum.length; i++) {
for (int j = 0; j < sum.length; j++) {
if (sum[i] < sum[j]) {
int temp = sum[i];
int temp2 = newTime[i];
sum[i] = sum[j];
sum[j] = temp;
newTime[i] = newTime[j];
newTime[j] = temp2;
}
}
}
System.out.println(Arrays.toString(sum));
System.out.println(Arrays.toString(newTime));
I have to create two arrays with ten random values between 0 and 20. With those arrays create two more arrays:
arrayReps contains the numbers that match between the two arrays. For example with arrays of 3 values: [3, 2, 4], [4, 5, 2] then arrayReps = [2, 4] (order doesnt matter)
arrayUniq contains the unique values of each of the original arrays. From the previous example, arrayUniq = [3, 5].
I already created the two random arrays, but i am having trouble on the arrayReps and arrayUniq, can you help me out? My Code:
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class P03ArraysExtractUniqsAndReps {
public static void main(String[] args){
Scanner scan1 = new Scanner(System.in);
Random number = new Random();
int a = 0;
int[] randomArray1;
randomArray1 = new int[10];
int[] randomArray2;
randomArray2 = new int[10];
int[] arrayUniq;
int[] arrayReps;
//int[] arrayUniq = new int[10];
for(int i = 0; i < 10; i++){
randomArray1[i] = number.nextInt(20);
}
for(int i = 0; i < 10; i++){
randomArray2[i] = number.nextInt(20);
}
System.out.println(Arrays.toString(randomArray1));
System.out.println(Arrays.toString(randomArray2));
}
}
Compare each element of a1 with the elements of a2. If the match is found, store that element in arrayReps, else store the element in arrayUniq
Something like this:
for(int i=0;i<a1.length;i++)
{
for(int j=0;j<a2.length;j++)
{
if(a1[i]==a2[j])
//add the element in arrayReps
else
//add the element in arrayUniq
}
}
you can also use bucket sort which is the most efficient and the conditions of bucketSort are met: the max and min values are known.
int[] bucketSortArray = new int[20];
for(int i=0;i<10;i++){
bucketSortArray[randomArray1[i]]++;
bucketSortArray[randomArray2[i]]++;
}
System.out.println(Arrays.toString(bucketSortArray));
if bucketSortArray[15]==1, than 15 is unique.
if bucketSortArray[20]>1, than 20 is in Reps.
if it's 0, ignore.
Here's one way of doing it.
Compare the first list of numbers against the second list, then whatever is left in the second list must also be unique.
import java.util.ArrayList;
public class UniqueArray {
public static void main(String[] args)
{
int[] list1 = {0,4,6,2,8,9};
int[] list2 = {0,4,3,2,7,5};
ArrayList<Integer> unique = new ArrayList<Integer>();
ArrayList<Integer> dups = new ArrayList<Integer>();
boolean isUnique = false;
int num;
for(int i = 0; i < list1.length; i++)
{
num = list1[i];
for(int j = 0; j < list1.length; j++)
{
isUnique = true;
if(list1[i] == list2[j])
{
isUnique = false;
list2[j] = -1; // mark as having already been found
break;
}
}
if(isUnique)
{
unique.add(num);
}
else
{
dups.add(num);
}
}
for(int i=0; i< list2.length; i++)
{
if(list2[i]!= -1)
{
unique.add(list2[i]);
}
}
System.out.println("Unique:");
System.out.println(unique);
System.out.println("Dups:");
System.out.println(dups);
}
}
Here is the solution, grab one or both as you wish:
Duplicates O(n+m)
public static int[] getDuplicates(int[] array1, int[] array2) {
HashSet<Integer> duplicates = new HashSet<>();
HashSet<Integer> uniques = new HashSet<>();
for(int i : array1) {
if (!uniques.add(i)) {
duplicates.add(i);
}
}
for(int j : array2) {
if (!uniques.add(j)) {
duplicates.add(j);
}
}
return duplicates.stream().mapToInt(i->i).toArray();
}
Uniques O(n+m)
public static int[] getUniques(int[] array1, int[] array2) {
HashSet<Integer> uniques = new HashSet<>();
for(int i : array1) {
uniques.add(i);
}
for (int j : array2) {
uniques.add(j);
}
return uniques.stream().mapToInt(i->i).toArray();
}
All at once O(n+m)
In case you don't want to use two methods, just put the body of getDuplicates(..) method (it calculates both of duplicates and uniques) to your main(..) one.
public static void main(String[] args) {
int[] array1 = {1,2,5,6,8,9,1};
int[] array2 = {3,4,5,6,0};
HashSet<Integer> setDuplicates = new HashSet<>();
HashSet<Integer> setUniques = new HashSet<>();
for (int i : array1) {
if (!setUniques.add(i)) {
setDuplicates.add(i);
}
}
for (int j : array2) {
if (!setUniques.add(j)) {
setDuplicates.add(j);
}
}
int[] duplicates = setDuplicates.stream().mapToInt(i->i).toArray();
int[] uniques = setUniques.stream().mapToInt(i->i).toArray();
System.out.println(Arrays.toString(duplicates));
System.out.println(Arrays.toString(uniques));
}
All methods will give you the same output:
Duplicates: [1, 5, 6]
Uniques: [0, 1, 2, 3, 4, 5, 6, 8, 9]