Compressing array values into another array - java

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)));
}

Related

how to reuse elements of an array out of its for loop?

I was trying to create a code that rearranges given elements in an array -by the user- in ascending order, and I have done that, but the program requires
printing the given elements after sorting them firstly, then printing them before sorting.
I have no problem with printing the elements after sorting
the problem is with printing them before sorting
how to re-use ar[S] = in.nextInt() the given elements by the user out of its for loop
import java.util.*;
public class SortingnumbersANDswapping {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int swap;
int ar[] = new int[3]; //{8,10,5}
for (int S = 0; S < ar.length; S++) {
ar[S] = in.nextInt(); //this for loop is used to store numbers in the array
}
for (int i = 0; i < ar.length; i++) {
/* this nested for loop is used to compare the first element with the second one in the array
or the second element with the third.
*/
for (int j = i + 1; j < ar.length; j++) {
if (ar[i] > ar[j]) { //8>10-->F , 8>5 -->T , {5,10,8} the new arrangment we are going to use
swap = ar[i]; // 10>8-->T {5,8,10}
ar[i] = ar[j];
ar[j] = swap;
}
}
System.out.println(ar[i]); // to print the new order print it inside the array
}
// I wanna do something like that
// System.out.println(ar[S]);
// but of course I cant cause array S is only defined in it's loop
}
}
You can't reuse it, you need to keep the original array stored in another array that stays untouched. Additionally, Arrays are usually declared as int[] ar in Java, instead of int ar[]. Something along the following lines should work as intended:
public class SortingnumbersANDswapping {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int swap;
int[] ar = new int[3]; //{8,10,5}
for (int S = 0; S < ar.length; S++) {
ar[S] = in.nextInt(); //this for loop is used to store numbers in the array
}
System.out.println("::: Original Array :::");
int[] originalArray = Arrays.copyOf(ar, ar.length);
for (int j : originalArray) {
System.out.println(j);
}
System.out.println("::: Sorted Array :::");
for (int i = 0; i < ar.length; i++) {
for (int j = i + 1; j < ar.length; j++) {
if (ar[i] > ar[j]) { //8>10-->F , 8>5 -->T , {5,10,8} the new arrangment we are going to use
swap = ar[i]; // 10>8-->T {5,8,10}
ar[i] = ar[j];
ar[j] = swap;
}
}
System.out.println(ar[i]); // to print the new order print it inside the array
}
}
}
You can do a copy of the array using the copyOf method from the Arrays library (java.util.Arrays) before you start changing the array.
Here you can find some different approaches - https://www.softwaretestinghelp.com/java-copy-array/amp/
You can use System.out.print(Arrays.toString(arr)); to print the entire array.
public static void main(String... args) {
int[] arr = readArray(3);
System.out.print(Arrays.toString(arr));
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < ar.length; j++) {
if (arr[i] > arr[j]) {
swap(arr, i, j);
System.out.print(Arrays.toString(arr));
}
}
}
}
private static int[] readArray(int size) {
System.out.format("Enter %d elements:\n", size);
Scanner scan = new Scanner(System.in);
int[] arr = new int[size];
for(itn i = 0; i < arr.length; i++)
arr[i] = scan.nextInt();
return arr;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}

How to create different column size in 2d array

I have two lists of elements and numbers but how can I put them into arrays if I don't know the exact array size? new int[elements.size()][I'm not sure about this size].
For example:
List of elements = [2,5]
List of numbers = [99,100], [1,9,8,10,70]
public static int[][] arrays(List<Integer> numbers, List<Integer> elements){
int count = 0;
int x = 0;
int y = 0;
int[][] list = new int[elements.size()][];
for (Integer e : elements) {
for (int i = count; i < count+e; i++) {
list[x][y] = numbers.get(i);
y++;
}
x++;
y = 0;
count += e;
}
return list;
}
The correct input for your method would be a list of lists, with each list in the parent list potentially having a different length:
public static int[][] arrays(List<List<Integer>> numbers) {
int[][] array = new int[numbers.size()][];
for (int i=0; i < numbers.size(); ++i) {
array[i] = new int[numbers.get(i).size()];
for (int j=0; j < numbers.get(i).size(); ++j) {
array[i][j] = numbers.get(i).get(j);
}
}
return array;
}

JAVA - Compare two arrays and create a new array with only the unique values from the first

I have to solve an exercise with the following criteria:
Compare two arrays:
int[] a1 = {1, 3, 7, 8, 2, 7, 9, 11};
int[] a2 = {3, 8, 7, 5, 13, 5, 12};
Create a new array int[] with only unique values from the first array. Result should look like this: int[] result = {1,2,9,11};
NOTE: I am not allowed to use ArrayList or Arrays class to solve this task.
I'm working with the following code, but the logic for the population loop is incorrect because it throws an out of bounds exception.
public static int[] removeDups(int[] a1, int[] a2) {
//count the number of duplicate values found in the first array
int dups = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
dups++;
}
}
}
//to find the size of the new array subtract the counter from the length of the first array
int size = a1.length - dups;
//create the size of the new array
int[] result = new int[size];
//populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
return result;
}
I would also love how to solve this with potentially one loop (learning purposes).
I offer following soulution.
Iterate over first array, and find out min and max it's value.
Create temporary array with length max-min+1 (you could use max + 1 as a length, but it could follow overhead when you have values e.g. starting from 100k).
Iterate over first array and mark existed values in temorary array.
Iterate over second array and unmark existed values in temporary array.
Place all marked values from temporary array into result array.
Code:
public static int[] getUnique(int[] one, int[] two) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < one.length; i++) {
min = one[i] < min ? one[i] : min;
max = one[i] > max ? one[i] : max;
}
int totalUnique = 0;
boolean[] tmp = new boolean[max - min + 1];
for (int i = 0; i < one.length; i++) {
int offs = one[i] - min;
totalUnique += tmp[offs] ? 0 : 1;
tmp[offs] = true;
}
for (int i = 0; i < two.length; i++) {
int offs = two[i] - min;
if (offs < 0 || offs >= tmp.length)
continue;
if (tmp[offs])
totalUnique--;
tmp[offs] = false;
}
int[] res = new int[totalUnique];
for (int i = 0, j = 0; i < tmp.length; i++)
if (tmp[i])
res[j++] = i + min;
return res;
}
For learning purposes, we won't be adding new tools.
Let's follow the same train of thought you had before and just correct the second part:
// populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
To this:
//populate the new array with the unique values
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
result[position] = a1[i];
position++;
}
}
I am assuming the "count" that you implemented was in attempt to prevent false-positive added to your result array (which would go over). When a human determines whether or not an array contains dups, he doesn't do "count", he simply compares the first number with the second array by going down the list and then if he sees a dup (a1[i] == a2[j]), he would say "oh it's not unique" (unique = false) and then stop going through the loop (break). Then he will add the number to the second array (result[i] = a1[i]).
So to combine the two loops as much as possible:
// Create a temp Array to keep the data for the loop
int[] temp = new int[a1.length];
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
temp[position] = a1[i];
position++;
}
}
// This part merely copies the temp array of the previous size into the proper sized smaller array
int[] result = new int[position];
for (int k = 0; k < result.length; k++) {
result[k] = temp[k];
}
Making your code work
Your code works fine if you correct the second loop. Look at the modifications I did:
//populate the new array with the unique values
int counter = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
result[counter] = a1[i];
counter++;
}
}
}
The way I would do it
Now, here is how I would create a method like this without the need to check for the duplicates more than once. Look below:
public static int[] removeDups(int[] a1, int[] a2) {
int[] result = null;
int size = 0;
OUTERMOST: for(int e1: a1) {
for(int e2: a2) {
if(e1 == e2)
continue OUTERMOST;
}
int[] temp = new int[++size];
if(result != null) {
for(int i = 0; i < result.length; i++) {
temp[i] = result[i];
}
}
temp[temp.length - 1] = e1;
result = temp;
}
return result;
}
Instead of creating the result array with a fixed size, it creates a new array with the appropriate size everytime a new duplicate is found. Note that it returns null if a1 is equal a2.
You can make another method to see if an element is contained in a list :
public static boolean contains(int element, int array[]) {
for (int iterator : array) {
if (element == iterator) {
return true;
}
}
return false;
}
Your main method will iterate each element and check if it is contained in the second:
int[] uniqueElements = new int[a1.length];
int index = 0;
for (int it : a1) {
if (!contains(it, a2)) {
uniqueElements[index] = it;
index++;
}
}

Is there a way to return an array into another array?

Is there a way to return an array into another array.
I have a multidimensional array which I am using a method combineArrays(Comparable[][] x) to combine into another 1D array.
Normally I'd just create the 1D array in a higher scope, but I've painfully learned that Comparable arrays need a dimension when initialized and the combineArrays() is responsible for determining the size of the mutliarray.
Please be kind, I'm not done yet.
The purpose of the program itself is to accept an array of objects and find a common list of object which exist in each row. The trick is the findCommonElements() must do so in either O(nlogn) or O(n) time
/*
* combs through the original array to find the shortest row which must hold
* the least # of common objects
*/
public static int findSmallestRow(Comparable[][] queries) {
int array_length = 0;
int indexOfMaster = 0;
array_length = queries[0].length; // sets variable to initial arrays row
// length
for (int i = 0; i < queries.length; i++) { // iterates through each row
// comparing size of each
// row
if (queries[i].length <= array_length) { // ensures the 1st row is,
// at minimum, the
// master array
array_length = queries[i].length;
indexOfMaster = i;
}
}
return indexOfMaster;
}
public static void findCommonElements(Comparable[][] queries){
Comparable[] new_query = combineArray(queries);
for(int a = 0; a<new_query.length; a++){
System.out.println(new_query[a]);
}
//Arrays.sort(new_query);
int query_length = new_query.length;
int masterIndex = findSmallestRow(queries);
Comparable extracted[] = new Comparable[queries[masterIndex].length];
System.arraycopy(queries[masterIndex], 0, extracted, 0,
extracted.length);
Comparable[] intermediate_query = new Comparable[masterIndex];
int nonquery_length = extracted.length;
int counter = 0;
int counter2 = 0;
int query_index = 0;
int nonquery_index = 0;
int i =0;
int j = 0;
while(i < nonquery_length && j < query_length){
if(extracted[nonquery_index].compareTo(new_query[query_index])>0){
query_index++;
}
if(extracted[nonquery_index].compareTo(new_query[query_index])<0){
nonquery_index++;
}
if(extracted[nonquery_index].compareTo(new_query[query_index])==0){
counter++;
if(counter == queries.length){
intermediate_query[counter2] = extracted[nonquery_index];
counter2++;
}
}
}
Comparable common_list[] = new Comparable[counter2];
for(int k = 0; k<counter2; k++){
common_list[k] = intermediate_query[k];
System.out.println(common_list[i]);
}
}
//gets size of query array, even if not uniform
public static Comparable[] combineArray(Comparable[][]queries){
int length = queries.length;
ArrayList rows = new ArrayList();
for(int i = 0; i< length; i++){
for(int k = 0; k<queries[i].length; k++){
rows.add("");
}
}
int query_size = rows.size();
Comparable[] new_query = new Comparable[query_size];
int new_query_counter = 0;
for(int i = 0; i< length; i++){
for(int k = 0; k<queries[i].length; k++){
new_query[new_query_counter] = queries[i][k];
}
}
return new_query;
}
This computes the set intersection of all the rows of the array.
public static Set<Comparable<?>> common( Comparable<?>[][] a ){
Set<Comparable<?>> inter = new HashSet<>( Arrays.asList( a[0] ) );
for( int i = 1; i < a.length; ++i ){
inter.retainAll( new HashSet<>( Arrays.asList( a[i] ) ) );
}
return inter;
}
It is possible that the original idea is to retain repeated elements, i.e., if there are two 'x' in each row, the result should also contain two 'x'. The short solution given hear uses sets, which do not store repetition of equal elements. - But here is a library where you find HashMultiSet, and the code will remain basically the same except for the types of inter and result.
import org.apache.commons.collections4.multiset.HashMultiSet;

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

Categories

Resources