Zipping two arrays in java - java

I would like to join two arrays but not like the usual way
{1,2,3} {4,5,6}
{1,2,3,4,5,6}
I would like to join them like so
{1,2,3} {4,5,6}
{1,4,2,5,3,6}
any suggestions?
I do not want to concatenate the two arrays but rather zip them

This Program also work for if array size of both is not equals.. Happy to help
public class Assignment{
public static void main(String[] args){
int [] arr1 = new int[]{1,2,3};
int [] arr2 = new int[]{4,5,6,7,8};
int [] arr3 = new int[arr1.length + arr2.length];
int biglength = 0;
if(arr1.length > arr2.length){
biglength = arr1.length;
}else{
biglength = arr2.length;
}
for(int i=0,j=0; i< biglength; i++){
if(i<arr1.length && i<arr2.length){
arr3[j++] = arr1[i];
arr3[j++] = arr2[i];
}else if(i<arr1.length){
arr3[j++] = arr1[i];
}else{
arr3[j++] = arr2[i];
}
}
for(int j= 0 ; j<arr3.length; j++){
System.out.print(arr3[j]);
}
}
}

Here is a technique using Java 8 streams:
int[] mergedArray = IntStream.range(0, Math.min(array1.length, array2.length))
.flatMap(n -> IntStream.of(array1[n], array2[n]))
.toArray();

VerA - on List and Integer, returned Integer[];
VerB - on array and int, returned int[];
Mixes n arrays where the length can be different.
public static Integer[] arraysMixVerA(Integer[]... arrays) {
List<Integer> list = new ArrayList<>();
int max=-1;
for (Integer[] array : arrays) {
max = Math.max(max, array.length);
}
for (int i = 0; i < max*arrays.length; i++) {
list.add(null);
}
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
list.set(j * arrays.length + i, arrays[i][j]);
}
}
for(int i=0;i<list.size();i++){
if(list.get(i)==null)
list.remove(i);
}
return list.toArray(new Integer[list.size()]);
}
public static int[] arraysMixVerB(int[]... arrays) {
int max=-1;
int sumaIndex=0;
for (int[] array : arrays) {
max = Math.max(max, array.length);
sumaIndex=sumaIndex+array.length;
}
Integer[] temp=new Integer[max*arrays.length]; //For an array of
//type int, the default value is 0. For an array of type Integer,
//the default value is null. Thus could not be distinguish zeros with arrays
//that are arguments methods of zeros from the array "temp".
int[] target=new int[sumaIndex];
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
temp[j * arrays.length + i]=arrays[i][j];
}
}
for(int i=0,j=0;i<temp.length;i++){
if(temp[i]!=null){
target[j++]=temp[i];
}
}
return target;
}

O(m) + O(n) is the maximum you can achieve here and accurate answered have already been provided here.
However if array size is extremity higher let's say 10^7 and if you'd want to reduce computation time little more by imposing on your machine cores and comfortable with slight complication in the code you can use concurrency here.
int[] arr1 = new int[10000010];
int[] arr2 = new int[10000000];
int end, endFinal;
int[] output = new int[arr1.length+arr2.length];
if( arr1.length < arr2.length )
end = arr1.length;
else
end = arr2.length;
endFinal = arr1.length + arr2.length;
T obj1 = new T( arr1, output, 0, end );
T obj2 = new T( arr2, output, 1, end );
Thread t1 = new Thread(obj1);
Thread t2 = new Thread(obj2);
t1.start();
t2.start();
t1.join();
t2.join();
for( int j = 2*end; j<endFinal; j++)
{
if(endFinal == arr1.length)
output[j] = arr1[end++];
else
output[j] = arr1[end++];
}
}
class T implements Runnable {
int[] arr, output;
int start, end;
public T ( int[] arr, int[] output, int start, int end)
{
this.arr = arr;
this.output = output;
this.start = start;
this.end = end;
}
public void run (){
int count = 0;
for (int i = start; i< end; i+=2)
output= arr[count++];
}
}
So both the threads will populate m number of elements assuming m is less than n and rest n - m forms will be populated normally. This may seem like a complicated solution and should only be used if necessary. One may not see the difference in smaller arrays.

Related

Creating an array that starts at n and ends at 0

I'm having difficulty with the action below. I'm not sure how to reverse the array index starting at n and working down to 0. Can someone help me understand this? I'm thinking of using a for loop, but I can't quite visualize how I would do that.
Thanks.
• Add a method called public static int[] generateIntegerArray(int n) to the App class that returns a systematically generated integer array of length n that is reverse sorted starting at n-1 and ending at 0. For example a call generateIntegerArray(5) would result in this array: {4, 3, 2, 1, 0}.
public static int[] generateIntegerArray(int n){
int[] integerArray = new int[n];
return integerArray;
}
Try something like this:
int[] integerArray = new int[n];
for(int i = 0; i < n; i++) {
integerArray[i] = n - i - 1;
}
return integerArray;
}
You should just fill that array with values from n-1 to 0
for(int i=0; i<n; i++) {
integerArray[i] = n-i-1;
}
or
for(int i=n; i>0; i--) {
integerArray[n-i-1] = i;
}
public static int[] generateIntegerArray(int n){
int[] integerArray = new int[n];
for(int i = n - 1; i >= 0; --i){
integerArray[n - 1 - i] = i;
}
return integerArray;
}
The for loop would run from n - 1 to 0 and the values would be put into array
for (int i = integerArray.length-1 ; i >=0; i--)
{
integerArray[i] = i;
}
That looks like(if lenght is 6, for example):
6,5,4,3,2,1,0
i - is number in loop, it changes in every loop(i--);
So, at the output it will looks like:
integerArray[6]
integerArray[5]
integerArray[4]
integerArray[3]
integerArray[2]
integerArray[1]
integerArray[0]
If I understood you in right way)
int[] integerArray = new int[]{1,2,3,4,5,6,7,8,9};
int[] reversedArray = new int[integerArray.length];
int j = 0;
for (int i = integerArray.length -1; i > 0; i--){
reversedArray[j++] = integerArray[i];
}
Hope you find this helpful..
public static int[] generateIntegerArray(int n){
int[] integerArray = new int[n];
for(int i = 0; i < n; i++) {
integerArray[i] = n - i - 1;
}
return integerArray;
}

Compressing array values into another array

I came across this problem called compress. The objective is to take an array, remove any repeated values and return a new array.
I know this would be very easy with ArrayLists, but I want to do it without them.
So far, I've just written a loop to determine the number of unique values so I can construct a new array of the appropriate length. How can I then get the unique values into the new array?
public static int[] compress(int[] array){
int length = 0;
boolean contains = false;
for (int i = 0; i < array.length; i++){
contains = false;
for (int j = 0; j < i; j++){
if (a[i] == a[j]){
contains = true;
j = i;
} else {
contains = false;
}
}
if (!contains){
length++;
}
}
int[] uniqueArray = new int[length];
}
Not Tested but I think this should do the trick.
public static int[] copyArray(int [] num){
int x = 0;
int numDuplicate = 0;
int[] copy = new int[num.length]; // we use this to copy the non duplicates
HashMap<Integer, Integer> count = new HashMap<>(); //hashmap to check duplicates
for(int i = 0; i < num.length; i++){
if(count.containsKey(num[i])){
count.put(num[i], count.get(num[i])+1);
numDuplicate++; // keep track of duplicates
}else{
count.put(num[i], 1); // first occurence
copy[x] = num[i]; // copy unique values, empty values will be at end
x++;
}
}
// return only what is needed
int newSize = num.length - numDuplicate;
int[] copyNum = new int[newSize];
for(int i = 0; i < copyNum.length; i++){
copyNum[i] = copy[i];
}
return copyNum;
}
public static void main(String[] args) {
// sample elements
int[] nums = new int[20];
for(int i = 0; i < nums.length; i++){
nums[i] = (int)(Math.random() * 20);
}
System.out.println(Arrays.toString(nums));
System.out.println(Arrays.toString(copyArray(nums)));
}

Inserting number into random array

I need some help inserting the number 8 into an array that gives me random values. The array must be in order. For example if I had an array of (1,5,10,15), I have to insert the number 8 between 5 and 10. I am having a problem on how I can figure our a way to find the index where 8 will be placed because the array is random, it can be anything. Here is my code so far :
public class TrickyInsert {
public static void main(String[] args) {
int[] mysteryArr = generateRandArr();
//print out starting state of mysteryArr:
System.out.print("start:\t");
for ( int a : mysteryArr ) {
System.out.print( a + ", ");
}
System.out.println();
//code starts below
// insert value '8' in the appropriate place in mysteryArr[]
int[] tmp = new int[mysteryArr.length + 1];
int b = mysteryArr.length;
for(int i = 0; i < mysteryArr.length; i++) {
tmp[i] = mysteryArr[i];
}
tmp[b] = 8;
for(int i =b ; i<mysteryArr.length; i++) {
tmp[i+1] = mysteryArr[i];
}
mysteryArr = tmp;
any tips? thanks!
Simply add the number then use Arrays.sort method,
int b = mysteryArr.length;
int[] tmp = new int[b + 1];
for(int i = 0; i < b; i++) {
tmp[i] = mysteryArr[i];
}
tmp[b] = 8;
mysteryArr = Arrays.sort(tmp);
In your example the random array is sorted. If this is the case, just insert 8 and sort again.
Simply copy the array over, add 8, and sort again.
int[] a = generateRandArr();
int[] b = Arrays.copyOf(a, a.length + 1);
b[a.length] = 8;
Arrays.sort(b);
int findPosition(int a, int[] inputArr)
{
for(int i = 0; i < inputArr.length; ++i)
if(inputArr[i] < a)
return i;
return -1;
}
int[] tmpArr = new int[mysteryArr.length + 1];
int a = 8; // or any other number
int x = findPosition(a, mysteryArr);
if(x == -1)
int i = 0;
for(; i < mysteryArr.length; ++i)
tmpArr[i] = mysteryArr[i];
tmpArr[i] = a;
else
for(int i = 0; i < mysteryArr.length + 1; ++i)
if(i < x)
tmpArr[i] = mysteryArr[i];
else if(i == x)
tmpArr = a;
else
tmpArr[i] = mysteryArr[i - 1];
I will suggest using binary search to find the appropriate index. Once you locate the index, you can use
System.arraycopy(Object src, int srcIndex, Obj dest, int destIndex, int length)
to copy the left half to your new array (with length one more than the existing one) and then the new element and finally the right half. This will stop the need to sort the whole array every time you insert an element.
Also, the following portion does not do anything.
for(int i =b ; i<mysteryArr.length; i++) {
tmp[i+1] = mysteryArr[i];
}
since int b = mysteryArr.length;, after setting int i =b ;, i<mysteryArr.length; will be false and hence the line inside this for loop will never execute.

Finding multiple modes in an array of integers with 1000 elements

So I need a way to find the mode(s) in an array of 1000 elements, with each element generated randomly using math.Random() from 0-300.
int[] nums = new int[1000];
for(int counter = 0; counter < nums.length; counter++)
nums[counter] = (int)(Math.random()*300);
int maxKey = 0;
int maxCounts = 0;
sortData(array);
int[] counts = new int[301];
for (int i = 0; i < array.length; i++)
{
counts[array[i]]++;
if (maxCounts < counts[array[i]])
{
maxCounts = counts[array[i]];
maxKey = array[i];
}
}
This is my current method, and it gives me the most occurring number, but if it turns out that something else occurred the same amount of times, it only outputs one number and ignore the rest.
WE ARE NOT ALLOWED TO USE ARRAYLIST or HASHMAP (teacher forbade it)
Please help me on how I can modify this code to generate an output of array that contains all the modes in the random array.
Thank you guys!
EDIT:
Thanks to you guys, I got it:
private static String calcMode(int[] array)
{
int[] counts = new int[array.length];
for (int i = 0; i < array.length; i++) {
counts[array[i]]++;
}
int max = counts[0];
for (int counter = 1; counter < counts.length; counter++) {
if (counts[counter] > max) {
max = counts[counter];
}
}
int[] modes = new int[array.length];
int j = 0;
for (int i = 0; i < counts.length; i++) {
if (counts[i] == max)
modes[j++] = array[i];
}
toString(modes);
return "";
}
public static void toString(int[] array)
{
System.out.print("{");
for(int element: array)
{
if(element > 0)
System.out.print(element + " ");
}
System.out.print("}");
}
Look at this, not full tested. But I think it implements what #ajb said:
private static int[] computeModes(int[] array)
{
int[] counts = new int[array.length];
for (int i = 0; i < array.length; i++) {
counts[array[i]]++;
}
int max = counts[0];
for (int counter = 1; counter < counts.length; counter++) {
if (counts[counter] > max) {
max = counts[counter];
}
}
int[] modes = new int[array.length];
int j = 0;
for (int i = 0; i < counts.length; i++) {
if (counts[i] == max)
modes[j++] = array[i];
}
return modes;
}
This will return an array int[] with the modes. It will contain a lot of 0s, because the result array (modes[]) has to be initialized with the same length of the array passed. Since it is possible that every element appears just one time.
When calling it at the main method:
public static void main(String args[])
{
int[] nums = new int[300];
for (int counter = 0; counter < nums.length; counter++)
nums[counter] = (int) (Math.random() * 300);
int[] modes = computeModes(nums);
for (int i : modes)
if (i != 0) // Discard 0's
System.out.println(i);
}
Your first approach is promising, you can expand it as follows:
for (int i = 0; i < array.length; i++)
{
counts[array[i]]++;
if (maxCounts < counts[array[i]])
{
maxCounts = counts[array[i]];
maxKey = array[i];
}
}
// Now counts holds the number of occurrences of any number x in counts[x]
// We want to find all modes: all x such that counts[x] == maxCounts
// First, we have to determine how many modes there are
int nModes = 0;
for (int i = 0; i < counts.length; i++)
{
// increase nModes if counts[i] == maxCounts
}
// Now we can create an array that has an entry for every mode:
int[] result = new int[nModes];
// And then fill it with all modes, e.g:
int modeCounter = 0;
for (int i = 0; i < counts.length; i++)
{
// if this is a mode, set result[modeCounter] = i and increase modeCounter
}
return result;
THIS USES AN ARRAYLIST but I thought I should answer this question anyways so that maybe you can use my thought process and remove the ArrayList usage yourself. That, and this could help another viewer.
Here's something that I came up with. I don't really have an explanation for it, but I might as well share my progress:
Method to take in an int array, and return that array with no duplicates ints:
public static int[] noDups(int[] myArray)
{
// create an Integer list for adding the unique numbers to
List<Integer> list = new ArrayList<Integer>();
list.add(myArray[0]); // first number in array will always be first
// number in list (loop starts at second number)
for (int i = 1; i < myArray.length; i++)
{
// if number in array after current number in array is different
if (myArray[i] != myArray[i - 1])
list.add(myArray[i]); // add it to the list
}
int[] returnArr = new int[list.size()]; // create the final return array
int count = 0;
for (int x : list) // for every Integer in the list of unique numbers
{
returnArr[count] = list.get(count); // add the list value to the array
count++; // move to the next element in the list and array
}
return returnArr; // return the ordered, unique array
}
Method to find the mode:
public static String findMode(int[] intSet)
{
Arrays.sort(intSet); // needs to be sorted
int[] noDupSet = noDups(intSet);
int[] modePositions = new int[noDupSet.length];
String modes = "modes: no modes."; boolean isMode = false;
int pos = 0;
for (int i = 0; i < intSet.length-1; i++)
{
if (intSet[i] != intSet[i + 1]) {
modePositions[pos]++;
pos++;
}
else {
modePositions[pos]++;
}
}
modePositions[pos]++;
for (int modeNum = 0; modeNum < modePositions.length; modeNum++)
{
if (modePositions[modeNum] > 1 && modePositions[modeNum] != intSet.length)
isMode = true;
}
List<Integer> MODES = new ArrayList<Integer>();
int maxModePos = 0;
if (isMode) {
for (int i = 0; i< modePositions.length;i++)
{
if (modePositions[maxModePos] < modePositions[i]) {
maxModePos = i;
}
}
MODES.add(maxModePos);
for (int i = 0; i < modePositions.length;i++)
{
if (modePositions[i] == modePositions[maxModePos] && i != maxModePos)
MODES.add(i);
}
// THIS LIMITS THERE TO BE ONLY TWO MODES
// TAKE THIS IF STATEMENT OUT IF YOU WANT MORE
if (MODES.size() > 2) {
modes = "modes: no modes.";
}
else {
modes = "mode(s): ";
for (int m : MODES)
{
modes += noDupSet[m] + ", ";
}
}
}
return modes.substring(0,modes.length() - 2);
}
Testing the methods:
public static void main(String args[])
{
int[] set = {4, 4, 5, 4, 3, 3, 3};
int[] set2 = {4, 4, 5, 4, 3, 3};
System.out.println(findMode(set)); // mode(s): 3, 4
System.out.println(findMode(set2)); // mode(s): 4
}
There is a logic error in the last part of constructing the modes array. The original code reads modes[j++] = array[i];. Instead, it should be modes[j++] = i. In other words, we need to add that number to the modes whose occurrence count is equal to the maximum occurrence count

how to get the most common character in an array?

Suppose I have an integer array like this:
{5,3,5,4,2}
and I have a method which returns the most common character
public int highestnumber(String[] num) {
int current_number = Integer.parseInt(num[0]);
int counter = 0;
for (int i = 1; i < num.length; ++i) {
if (current_number == Integer.parseInt(num[i])) {
++counter;
} else if (counter == 0) {
current_number = Integer.parseInt(num[i]);
++counter;
} else {
--counter;
}
}
return current_number;
}
but if I have multiple common character then i need to get the number which is closest to one(1), like if i have an array like this:
{5,5,4,4,2};
then the method should return 4, what should I do for this?
As per what I understand your question,
What you have to done is,
1. Create ArrayList from your int[]
2. Use HashMap for find duplicates, which one is unique
3. Sort it as Ascending order,
4. First element is what you want..
EDIT: Answer for your question
int[] arr = {5, 4, 5, 4, 2};
ArrayList<Integer> resultArray = new ArrayList<Integer>();
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < arr.length; i++)
{
if (set.contains(arr[i]))
{
System.out.println("Duplicate value found at index: " + i);
System.out.println("Duplicate value: " + arr[i]);
resultArray.add(arr[i]);
}
else
{
set.add(arr[i]);
}
}
Collections.sort(resultArray);
for (int i = 0; i < resultArray.size(); i++)
{
Log.e("Duplicate Values:", resultArray.get(i) + "");
}
Your need is,
int values = resultArray.get(0);
Sort the array then count runs of values.
Fast way.
Create a counter int array one element for each number. Go through the array once and increment corresponding counter array for each number. Set highest number to first counter element then go through and change highest number to current element only if it is bigger than highest number, return highest number.
public int highestNumber(String[] num){
int[] count = new int[10];
int highest_number = 0;
int highest_value = 0;
for(int i = 0; i < num.length; i++)
count[Integer.parseInt(num[i])]++;;
for(int i = 0; i < count.length; i++)
if(count[i] > highest_value){
highest_number = i;
highest_value = count[i];
}
return highest_number;
}
10x slower but without other array.
Create three ints one for number and two for counting. Go through the array once for each int and increment current counting each time it shows up, if bigger that highest count, set to highest count and set highest number to current count. Return highest number.
public int highestNumber(String[] num){
int highest_number = 0;
int highest_value = 0;
int current_value = 0;
for(int i = 0; i < 10; i++){
for(int j = 0; j < num.length; j++)
if(i == Integer.parseInt(num[j]))
current_value++;
if(current_value > highest_value){
highest_value = current_value;
highest_number = i;
}
current_value = 0;
}
return highest_number;
}
The first is obviously much faster but if for whatever reason you don't want another array the second one works too.
You can also try this:
import java.util.TreeMap;
public class SmallestFrequentNumberFinder {
public static int[] stringToIntegerArray(String[] stringArray) {
int[] integerArray = new int[stringArray.length];
for (int i = 0; i < stringArray.length; i++) {
integerArray[i] = Integer.parseInt(stringArray[i]);
}
return integerArray;
}
public static int getSmallestFrequentNumber(int[] numbers) {
int max = -1;
Integer smallestFrequentNumber = null;
TreeMap<Integer, Integer> frequencyMaper = new TreeMap<Integer, Integer>();
for (int number : numbers) {
Integer frequency = frequencyMaper.get(number);
frequencyMaper.put(number, (frequency == null) ? 1 : frequency + 1);
}
for (int number : frequencyMaper.keySet()) {
Integer frequency = frequencyMaper.get(number);
if (frequency != null && frequency > max) {
max = frequency;
smallestFrequentNumber = number;
}
}
return smallestFrequentNumber;
}
public static void main(String args[]) {
String[] numbersAsString = {"5", "5", "4", "2", "4", "4", "2", "2"};
final int[] integerArray = stringToIntegerArray(numbersAsString);
System.out.println(getSmallestFrequentNumber(integerArray));
}
}

Categories

Resources