Related
Currently working on a method that takes a n*n matrix as input and returns an array consisting of all elements that are found in each sub-array. However, since I need it to also include duplicates etc, it's harder than I thought.
Googled the hell out of it, however, yet to find a solution which matches my criteria of repetition.
Currently I have this, which compares the element's of the first row with every other row and all their elements. If the counter gets to the length where it confirms that the element indeed is present in all rows, it adds it to the array. However, this has faults in it. First of all, since I create a set array in the beginning with the maximum possible length, it might return an array with non-needed 0's in it. And second, the duplicate part is not working correctly, struggling to implement a check there.
Examples of input/output that I need:
Input matrix: {{2,2,1,4},{4,1,2,2},{7,1,2,2},{2,10,2,1}}
Desired output: {1, 2, 2}
My output: {2, 2, 1, 0}
Input matrix: {{2,2,1,4},{4,1,3,2},{7,1,9,2},{2,10,2,1}}
Desired output: {1, 2}
My output: {2, 2, 1, 0}
public static int[] common_elements(int[][] matrix){
int[] final_array = new int[matrix.length];
for (int i = 0; i < matrix.length; i++) {
int counter = 0;
for (int j = 1; j < matrix.length; j++) {
for (int k = 0; k < matrix.length; k++) {
if(matrix.[0][i] == matrix.[j][k]){
counter += 1;
break;
}
}
}
if(counter == a.length-1){
final_array[i] = a[0][i];
}
}
return final_array;
}
EDIT: This is what I finally got together that fits my requirements and works flawlessly, with comments
public static int[] repetitiveInts(int[][] a){
//This is a method declared outside for sorting every row of the matrix ascending-ly before I do the element search.
for (int i = 0; i < a.length; i++) {
sorting(a[i]);
}
//Declaring a LinkedList in order to add elements on the go
LinkedList<Integer> final_list= new LinkedList<Integer>();
//Iterating through the matrix with every element of the first row, counting if it appears in every row besides the first one.
for (int i = 0; i < a.length; i++) {
int counter = 0;
for (int j = 1; j < a.length; j++) {
for (int k = 0; k < a.length; k++) {
//Checking if an element from the other rows match
if(a[0][i] == a[j][k]){
a[j][k] = a[0][i]-1; //If a match is found, the element is changed so finding duplicates is possible.
counter += 1;
break; //Breaking and checking the next row after one row checks out successfully.
}
}
}
//If the element is indeed in every row, adds it to the lit.
if(counter == a.length-1){
final_list.add(a[0][i]);
}
}
//Since I had to return a regular int[] array, converting the LinkedList into an array.
int[] final_realarray= new int[final_list.size()];
for (int i = 0; i < final_list.size(); i++) {
final_realarray[i] = final_list.get(i);
}
return final_realarray;
Grateful for help :)
The most efficient way to solve this problem is by creating a histogram of frequencies for each nested array in the matrix (i.e. determine the number of occurrences for every element in the nested array).
Every histogram will be represented by a Map<Integer, Integer> (array element as a key, its occurrences as a value). To generate a histogram only a single pass through the array is needed. In the solution below this logic resides inside the getFrequencies() method.
After creating all histograms we have to merge them. In terms of set theory we are looking for an intersection of keys in all histograms. I.e. we need only those keys that appear at least once in every histogram and a value for each key will be the smallest in all histograms for that key. This logic is placed in the getCommonElements().
In order to create a merged histogram, we can pick any of the histograms (in the code below the first histogram is used frequencies.get(0).keySet()) and iterate over its keys. Then in the nested loop, for every key, we need to find the minimum value associated with that in every histogram in a list (reminder: that will be the smallest number of occurrences for the key).
At the same time, while merging histograms we can also find the length of the resulting array by adding all the minimal frequencies together. That small optimization will allow to avoid doing the second iteration over the merged map.
The last step required is to populate the resulting array commonElements with keys from the merged histogram. Value of every key denotes how many times it has to be placed in the resulting array.
public static void main(String[] args) {
System.out.println(Arrays.toString(commonElements(new int[][]{{2,2,1,4},{4,1,2,2},{7,1,2,2},{2,10,2,1}})));
System.out.println(Arrays.toString(commonElements(new int[][]{{2,2,1,4},{4,1,3,2},{7,1,9,2},{2,10,2,1}})));
}
public static int[] commonElements(int[][] matrix){
List<Map<Integer, Integer>> frequencies = getFrequencies(matrix);
return getCommonElements(frequencies);
}
private static List<Map<Integer, Integer>> getFrequencies(int[][] matrix) {
List<Map<Integer, Integer>> frequencies = new ArrayList<>();
for (int[] arr: matrix) {
Map<Integer, Integer> hist = new HashMap<>(); // a histogram of frequencies for a particular array
for (int next: arr) {
// hist.merge(next, 1, Integer::sum); Java 8 alternative to if-else below
if (hist.containsKey(next)) {
hist.put(next, hist.get(next) + 1);
} else {
hist.put(next, 1);
}
}
frequencies.add(hist);
}
return frequencies;
}
private static int[] getCommonElements(List<Map<Integer, Integer>> frequencies) {
if (frequencies.isEmpty()) { // return an empty array in case if no common elements were found
return new int[0];
}
Map<Integer, Integer> intersection = new HashMap<>();
int length = 0;
for (Integer key: frequencies.get(0).keySet()) { //
int minCount = frequencies.get(0).get(key); // min number of occurrences of the key in all maps
for (Map<Integer, Integer> map: frequencies) {
int nextCount = map.getOrDefault(key, 0);
minCount = Math.min(nextCount, minCount); // getOrDefault is used because key might not be present
if (nextCount == 0) { // this key isn't present in one of the maps, no need to check others
break;
}
}
if (minCount > 0) {
intersection.put(key, minCount);
length += minCount;
}
}
int[] commonElements = new int[length];
int ind = 0;
for (int key: intersection.keySet()) {
int occurrences = intersection.get(key);
for (int i = 0; i < occurrences; i++) {
commonElements[ind] = key;
ind++;
}
}
return commonElements;
}
output
[1, 2, 2]
[1, 2]
Side note: don't violate the naming conventions, use camel-case for method and variable names.
Update
I've managed to implement a brute-force solution based on arrays and lists only as required.
The most important thing is that for this task you need two lists: one to store elements, another to store frequencies. Lists are bound together via indices. And these two lists are basically mimic a map, frankly saying a very inefficient one (but that's a requirement). Another possibility is to implement a class with two int fields that will represent the data for a common element, and then store the instances of this class in a single list. But in this case, the process of checking whether a particular element already exists in the list will be much more verbose.
The overall logic has some similarities with the solution above.
First, we need to pick a single array in the matrix (matrix[0]) and compare all its unique elements against the contents of all other arrays. Every element with non-zero frequency will be reflected in the list of elements and in the list of frequencies at the same index in both. And when the resulting array is being created the code relies on the corresponding indices in these lists.
public static int[] commonElements(int[][] matrix){
if (matrix.length == 0) { // case when matrix is empty - this condition is required because farther steps will lead to IndexOutOfBoundsException
return new int[0];
}
if (matrix.length == 1) { // a small optimization
return matrix[0];
}
// Map<Integer, Integer> frequencyByElement = new HashMap<>(); // to lists will be used instead of Map, because of specific requirement for this task
List<Integer> frequencies = new ArrayList<>(); // lists will be bind together by index
List<Integer> elements = new ArrayList<>();
int length = 0; // length of the resulting array
for (int i = 0; i < matrix[0].length; i++) {
if (elements.contains(matrix[0][i])) { // that means this element is a duplicate, no need to double-count it
continue;
}
int currentElement = matrix[0][i];
int minElementCount = matrix[0].length; // min number of occurrences - initialized to the max possible number of occurrences for the current array
// iterating over the all nested arrays in matrix
for (int row = 0; row < matrix.length; row++) {
int localCount = 0; // frequency
for (int col = 0; col < matrix[row].length; col++) {
if(matrix[row][col] == currentElement){
localCount++;
}
}
if (localCount == 0) { // element is absent in this array and therefore has to be discarded
minElementCount = 0;
break; // no need to iterate any farther, breaking the nested loop
}
minElementCount = Math.min(localCount, minElementCount); // adjusting the value the min count
}
// frequencyByElement.put(currentElement, minElementCount); // now we are sure that element is present in all nested arrays
frequencies.add(minElementCount);
elements.add(currentElement);
length += minElementCount; // incrementing length
}
return getFinalArray(frequencies, elements, length);
}
private static int[] getFinalArray(List<Integer> frequencies,
List<Integer> elements,
int length) {
int[] finalArray = new int[length];
int idx = 0; // array index
for (int i = 0; i < elements.size(); i++) {
int element = elements.get(i);
int elementCount = frequencies.get(i);
for (int j = 0; j < elementCount; j++) {
finalArray[idx] = element;
idx++;
}
}
return finalArray;
}
I'm new to Java, and I'm not sure how to ask the right question, so please bear with me. I have 40 total items of 6 different types to put into a new array; each item type has a different cost. The first item (quantity=1) costs $3, the second item (qty=2) costs $5 each, the third item (qty=4) costs $9 each, and so on. The quantity of each item type is in numTypeIndArray and the cost for each type is in costCSDriverArray. A cumulative count of the total items is in numTypeCumulArray.
So, the new array, indItemCostArray, should be single dimensional and have 40 elements. It would look something like {3,5,5,9,9,9,9,...,13,13,13}, but the last fifteen elements are a cost of $13. How do I get to this array with 40 elements? I started with trying to fill the array using a nested for loop but I haven't gotten there yet. The code below is plain wrong.
int[] costArray = new int[]{3,5,9,10,11,13};
int[] numTypeIndArray = new int[]{1,2,4,7,11,15};
int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
int[] indItemCostArray = new int[numTypeCumulArray[6]];
for (int i = 0; i < indItemCostArray.length; i++) {
for (int j = 0; j < numTypeIndArray[i]; j++) {
indItemCostArray[i+j] = costArray[j];
}
}
First of all, you'll get a ArrayOutOfBoundException at:
int[] indItemCostArray = new int[numTypeCumulArray[6]];
The size of the array numTypeCumulArray is 6, and arrays are 0 indexed. So, The last index number is 5, not 6, as indexing started from 0.
You can do as follows for accessing the last element of the array:
int[] indItemCostArray = new int[numTypeCumulArray[numTypeCumulArray.length - 1]];
Secondly, you're running your outer loop for 40 times and for each iteration your inner loop is trying to iterate for numTypeIndArray[i] times, where i is the iterator variable of outer loop. So, surely after sixth iteration, when value of i will be 6, your program will again throw the ArrayOutOfBoundException as you're accessing a value in the terminator condition of the inner loop from numTypeIndArray whose last index is 5.
Again, inside the inner loop, you're assigning indItemCostArray at index position i+j, which will actually far from your purpose.
To achieve what you are exactly expecting, you can do as follows:
int currentIndex =0;
for (int costIndex = 0; costIndex < costArray.length; costIndex++) {
for(int index = currentIndex; index < currentIndex + numTypeIndArray[costIndex]; index++) {
indItemCostArray[index] = costArray[costIndex];
}
currentIndex = numTypeCumulArray[costIndex];
}
Here, what I did is, in the outer loop I iterated the same amount of time the length of costArray, you can take the length of numTypeIndArray instead too, no issue. I've defined a variable named currentIndex to keep track of the current assignable index for array indItemCostArray. In the inner loop, I tried to begin with the currentIndex and loop upto the time same as the number of items needed for that type, given in numTypeIndArray[costIndex], and for each iteration, set the corresponding index of indItemCostArray with the cost of costIndex in the costArray. Finally, I update the currentIndex with the corresponding cumulative total items from numTypeCumulArray.
Hope you got everything clear.
The whole setup of three arrays is kind of weird. The weiredest is the third array. Think carefully, do you actually need it? You already have all the information in your second array. The third array can introduce a lot of unnacessary mistakes.
But, assuming that you actually need these arrays for some reason and there are no mistakes in making these arrays. You can get your required fourth array as follows,
int[] costArray = new int[]{3,5,9,10,11,13};
int[] numTypeIndArray = new int[]{1,2,4,7,11,15};
int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
// you want to make sure that your arrays are of same lenght
assert(costArray.length == numTypeIndArray.length && costArray.length == numTypeCumulArray.length);
// length of these arrays is unique items count
int uniqueItemsCount = costArray.length;
// totalItemsCount is last element of numTypeCumulArray
int totalItemsCount = numTypeCumulArray[uniqueItemsCount - 1];
int[] indItemCostArray = new int[totalItemsCount];
// use this to keep track of index in indItemCostArray
int itemCostIndex = 0;
for (int i = 0; i < uniqueItemsCount && itemCostIndex < totalItemsCount; i++) {
for (int j = 0; j < numTypeIndArray[i] && itemCostIndex < totalItemsCount; j++) {
indItemCostArray[itemCostIndex] = costArray[j];
// increase the index for next item cost
itemCostIndex += 1;
}
}
int[] costArray = new int[]{3,5,9,10,11,13};
int[] numTypeIndArray = new int[]{1,2,4,7,11,15};
int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
int[] indItemCostArray = new int[numTypeCumulArray[5]];
int num = 0;
for (int i = 0; i < numTypeIndArray.length; i++) {
for (int j = 0; j < numTypeIndArray[i]; j++) {
indItemCostArray[num + j] = costArray[i];
}
num += numTypeIndArray[i];
}
System.out.println(Arrays.toString(indItemCostArray));
First, you don't need int[] numTypeCumulArray = new int[]{1,3,7,14,25,40};
It just shows the cumulative values of the numTypeIndArray. The last value, 40 is just the sum of numTypeIndArray and that would be the size of the resulting array from your requirement.
It can be summed in a simple for loop or you can do it like this and then create the target array.
int maxSize = Arrays.stream(numTypeIndArray).sum();
int[] indItemCostArray = new int[maxSize];
Then you could proceed to populate the array with the values as has been shown. Here is another way using streams which you will undoubtedly learn about. The quick explanation is that it creates multiple streams of the proper quantities of cost.
e.g
stream1 -> {3}
stream2 -> {5,5};
stream3 -> {9,9,9,9} etc.
Then it flattens them in a single stream of those values and returns an array.
int[] result = IntStream.range(0, costArray.length)
.flatMap(i -> IntStream.range(0, numTypeIndArray[i])
.map(q -> costArray[i]))
.toArray();
But using a class to hold the information would be better. Here is one example.
class Product {
private String name;
private int cost;
private int quantity;
public Product(String name, int cost, int quantity) {
this.name = name;
this.cost = cost;
this.quantity = quantity;
}
public int getCost() {
return cost;
}
public int getQuantity() {
return quantity;
}
public String getName() {
return name;
}
#Override
public String toString() {
return new StringJoiner(", ","[", "]").add(name).add("cost="+cost).add("quantity="+quantity).toString();
}
}
And it can be used like so.
List<Product> products = new ArrayList<>();
for (int i = 0; i < costArray.length; i++) {
products.add(new Product("Item" + (i+1), costArray[i], numTypeIndArray[i]));
}
products.forEach(System.out::println);
Prints
[Item1, cost=3, quantity=1]
[Item2, cost=5, quantity=2]
[Item3, cost=9, quantity=4]
[Item4, cost=10, quantity=7]
[Item5, cost=11, quantity=11]
[Item6, cost=13, quantity=15]
And once again it can be streamed to create your results exactly as before only using the class getters to get the values.
int[] result2 = products.stream()
.flatMapToInt(
prod -> IntStream.range(0, prod.getQuantity())
.map(q -> prod.getCost()))
.toArray();
The two arrays result and result2 are identical. But you may find that using classes may eliminate the requirement for creating such an array.
I have a problem with one of our old exam tasks.
the task is
"the method positions should return a field containing exactly the positions of those elements of the list that have null as content. if there are no such elements than return a field with the length 0"
the code starts with :
public int[] positions() {
int[] result = new int[0];
I keep getting stuck on because of the "new int[0]" when I tried solving the problem without it I managed to get somewhat of a result. but I don't know how to do it with this part.
Just think for a moment what the code is doing here.
int[] result = new int[0];
creates an empty, fixed lenght, primitive array. This array cannot be further expanded.
Your exam task would be translated as (simplifying at a large degree):
public int[] positions(final Object[] objects) {
// Initialize the array with the max possible size, which is the input array size
final int[] positions = new int[objects.lenght];
int j = 0;
for (int i = 0; i < objects.length; i++) {
if (objects[i] == null) {
// Assign the index of the null value to the holder array.
// Increment j, which is the index of the first free position in the holder array
positions[j++] = i;
}
}
// This will return a copy of the "positions" array, truncated at size j
return Array.copyOf(positions, j);
}
I have a JLabel array that starts with an integer number of elements. How can I remove an certain number of elements from the array? For example, every time the int is updated:
int i = 21;
i = i - removedElements
How can I update the array to contain that many elements, instead of creating an entirely new array with the desired number of elements?
As others have already mentioned, List is the way to go here since it is specifically designed for adding and or deleting elements.
However if you would prefer to use the JLabel Array you already have in established then you will need to realize that the only way to delete an element from that array is to actually create another array with the desired element to delete excluded from it then return it into the original array. Below I have supplied a simple method named deleteJLabelFromArray() that can do this for you:
public static JLabel[] deleteJLabelFromArray(JLabel[] srcArray, int... indexesToDelete) {
int counter = 0;
JLabel[] newArray = new JLabel[srcArray.length - indexesToDelete.length];
for (int i = 0; i < srcArray.length; i++) {
boolean noGo = false;
for (int j = 0; j < indexesToDelete.length; j++) {
if (i == indexesToDelete[j]) { noGo = true; break; }
}
if (noGo == false) { newArray[counter] = srcArray[i]; counter++; }
}
return newArray;
}
With this method you can delete whatever indexes you supply within the indexesToDelete argument (delimited with a comma). Copy/Paste the code into your project then you can use it something like this:
JLabel[] jla = {jLabel2,jLabel3,jLabel4,jLabel5};
jla = deleteJLabelFromArray(jla, 2);
for (int i = 0; i < jla.length; i++) {
System.out.println(jla[i]);
}
In this example we are going to delete the element number 2 (remember that arrays are 0 based) and therefore jLabel4 would be removed from the Array.
Keep in mind that this would be scary stuff with really big arrays.
Hope this helps.
Here's what the layout is
index num
0 [10]
1 [20]
2 [30]
(Add 35 here)
3 [40] Move elements down
4 [50]
5 [60]
6 [70]
then my method is this
public static void method(int[] num, int index, int addnum)
{
}
How can i add 35 in there?
Tried this:
public static void method(int[] num, int index, int addnum)
{
int index = 10;
for(int k = num.length k>3; k++)
{
Num[k]=num[k++]
}
Num[3] = 35;
As this is something you should accomplish yourself, I will only provide the method to implement it, not the code:
If you would set the number at position index, you would overwrite the value that was there previously. So what you need to do is move every element one position towards the end of the array starting from index: num[x] becomes num[x+1], etc.
You will find out that you need to do this in reverse order, otherwise you will fill your array with the value in num[index].
During this process you will need to decide what to do with the last entry of the array (num[num.length - 1]):
You could just overwrite it, discarding the value
You could return it from your function
You could throw an exception if it is non-zero
You could create a new array that is 1 entry larger than the current array instead to keep all values
etc.
After this, you have duplicated num[index]: the value is present in num[index+1], too, as you have moved it away.
Now it is possible to write the new value at the desired position without overriding an existing value.
EDIT
You have several errors in your code:
You increment k, you need to decrement it (k--, not k++)
You modify k again in your loop body: it is updated twice in each cycle
If you start with k = num.length, you will try to write at num[num.length + 1], which is not possible
Very crudely, you want to do something like this:
public static void(int[] num, int index, int addnum)
{
// initialize new array with size of current array plus room for new element
int[] newArray = new int[num.length + 1];
// loop until we reach point of insertion of new element
// copy the value from the same position in old array over to
// same position in new array
for(int i = 0; i < index; i++)
{
newArray[i] = num[i];
}
i = i + 1; // move to position to insert new value
newArray[i] = addnum; // insert the value
// loop until you reach the length of the old array
while(i < num.length)
{
newArray[i] = num[i-1];
}
// finally copy last value over
newArray[i + 1] = num[i];
}
You need to
allocate a new array with room for one new element.
int[] newArray = new int[oldArray.length + 1];
Copy over all elements and leave room for the one to insert.
for (int i = 0; i < newArray.length - 1; i++)
newArray[i < insertIndex ? i : i + 1] = oldArray[i];
Insert 35 in the empty spot.
newArray[insertIndex] = numberToInsert;
Note that it's not possible to do in a method like this:
public static void method(int[] num, int index, int addnum)
^^^^
since you can't change the length of num.
You need to allocate a new array, which means that need to return the new array:
public static int[] method(int[] num, int index, int addnum)
^^^^^
and then call the method like this:
myArr = method(myArr, 3, 35);
Since this very closely resembles homework what you need to realize is that you cannot dynamically increase the size of an array. So in your function:
public static void(int[] num, int index, int addnum)
{
int[] temp = new int[num.length *2];
for(int i = 0; i < index; i++)
copy num[i] into temp[i]
insert addnum into temp[index]
fill temp with remaining num values
}
That pseudocode above should get you started.
What you're looking for is an insertion sort.
It's classwork, so it's up to you to figure out the proper code.
Well, you can't unless there is "extra space" in your array, and then you can shift all elements [starting from index] one element to the right, and add 35 [num] to the relevant place.
[what actually happen is that the last element is discarded out].
However - a better solution will probably be to use an ArrayList, and use the method myArrayList.add(index,element)
How about this?
public class test {
public static void main(String[] arg) throws IOException
{
int[] myarray={1,2,3,5,6};//4 is missing we are going to add 4
int[] temp_myarray=myarray;//take a temp array
myarray=addElement(myarray,0);//increase length of myarray and add any value(I take 0) to the end
for(int i=0;i<myarray.length;i++)
{ if(i==3) //becaues I want to add the value 4 in 4th place
myarray[i]=4;
else if(i>3)
myarray[i]=temp_myarray[i-1];
else
myarray[i]=temp_myarray[i];
}
for(int i=0;i<myarray.length;i++)
System.out.print(myarray[i]);//Print new array
}
static int[] addElement(int[] arr, int elem) {
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = elem;
return arr;
}
}