Finding adjacent elements in a 2d array and counting them. - java

Im stumped on what to do for this part of my homework and could really use some help. I need to cycle through a given 2d array and find all similar elements that are adjacent to another and count that so for example
AA--B
AA--B
-AA--
----C
So the count would be 3 one for the As one for the Bs and one for the C, I just kinda need an idea where to start So far i have
public static int howManyOrganisms(char[][] image){
int count = 0;
for (int i = 0; i < image.length; i++) {
for (int j = 0; j < image[i].length; j++) {
if(image[i][j] != '-') {
count++;
}
System.out.println();
}
return howManyOrganisms(image, count);
}
}
I need help figuring out how to track the total number of elements that are within contact of one another (so left, right, down, up) being another similar element.

In each iteration, you can use your i,j variables to "navigate" the 2d plane and see if any interacting items are the same. In each iteration you would check the following indexes to see if they are the same:
image[i-1][j] (one row up)
image[i+1][j] (one row down)
image[i][j-1] (one left)
image[i][j+1] (one right)
Of course for all of these statements first you should check if +1/-1 is still within the size of your matrix, otherwise you will end up with out of bounds exception.

Related

Optimize the time complexity of program which computes the number of different pairs of numbers like described below

As I am pretty new to java, I'm struggeling with optimization of the time complexity of my programs. I have written a simple code which takes an array, and counts how many pairs of numbers there are for which the element with the lower index in the array is greater than the element with the greater index.
For example, if you have the array: [9,8,12,14,10,54,41], there will be 4 such pairs: (9,8),(12,10),(14,10) and (54,41).
I tried to optimize the code by not just comparing every element with every other one. I aimed for a time complexity of n log n. I have not yet figured out a way to write this code in a more efficient manner. I hope my question is clear.
The code(I have omitted adding the heapsort code, as it's not related to my question.)
import java.util.Scanner;
class Main4 {
static int n;
static int[] A;
// "A" is the input vector.
// The number of elements of A can be accessed using A.length
static int solve(int[] A) {
int counter = 0;
int[] B = new int[n];
B = A.clone();
heapSort(B);
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length; j++) {
while( B[j] == Integer.MIN_VALUE&&j+1<n) {
j=j+1;
}
if (A[i] != B[j]) {
counter++;
} else {
B[j] = Integer.MIN_VALUE;
break;
}
}
}
return counter; }
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int ntestcases = scanner.nextInt();
for (int testno = 0; testno < ntestcases; testno++) {
n = scanner.nextInt();
A = new int[n];
for (int i = 0; i < n; i++)
A[i] = scanner.nextInt();
System.out.println(solve(A));
}
scanner.close();
}
}
Divide and conquer 1 (merge-sort like)
Split the whole list W into two parts L and R of early equal lengths. The count for W is the sum of
counts for L and R
the number of pairs (l, r) with l > r where l and r belong to L and R respectively.
The first bullet is recursion. The second bullet does not depend of the ordering of the lists L and R. So you can sort them and determine the result using a single pass through both lists (count all smaller r in sorted R for the first element of sorted L, the count for the second can now be computed incrementally, etc).
The time complexity is given by
T(n) = T(n/2) + T(n/2) + O(n log n)
which I guess is O(n log n). Anyway, it's much smaller than O(n*n).
You could improve it a bit by using merge sort: You need sorted L and this can be obtained by merging sorted LL and sorted LR (which are the two parts of L in the recursive step).
Divide and conquer 2 (quick-sort like)
Select an element m such that the number of bigger and smaller elements is about the same (the median would be perfect, but a randomly chosen element is usable, too).
Do a single pass through the array and count how many elements smaller than m are there. Do a second pass and count the pairs (x, y) with x placed to the left of y and x >= m and m > y.
Split the list into two parts: elements e >= m and the remaining ones. Rinse and repeat.
You are looking for all possible pairs.
You can check from left to right to find all the matches. That's O(n^2) solution. As suggested by Arkadiy in the comments, this solution is okay for the worst case of the input.
I came up with the idea that you might want to store elements in sorted order AND keep the original unsorted array.
You keep the original array and build binary search tree. You can find the element with original index i in time O(lgn) and remove it in O(lgn), which is great. You can also determine the number of values smaller than ith element with tiny additional cost.
To be able to count the elements smaller than, each node has to store the number of its children + 1. When you remove, you simply decrement the number of children in each node on your way down. When you insert, you increment the number of children in each node on your way down. When you search for a node you store the value root node has in variable and
do nothing when you go to the right child,
subtract the number child has from your variable when you go to the left child
Once you stop (you found the node), you subtract the value right child has (0 if there is no right child) and decrement the value.
You iterate over the original array from left to right. At each step you find element in your tree and calculate how many elements that are smaller are in tree. You know how many smaller than your current are there and you also know that all elements in the tree have greater index than the current element, which know how many elements you can pair it up with! You remove this element from the tree after you calculate the number of pairs. You do that n times. Lookup and removing from the tree is O(lgn) == O(nlgn) time complexity! The total time is O(nlgn + nlgn) = O(nlgn)!!
Chapter 12 of Introduction to algorithms (3rd edition) explains in depth how to implement BST. You may also find many resources on the Internet that explain it with pictures.

Understanding this remove method solution with arrayList [duplicate]

This question already has answers here:
Understanding this removeAll java method with arrayList
(3 answers)
Closed 6 years ago.
This methods duty is to remove all occurrences of the value toRemove from the arrayList. The remaining elements should just be shifted toward the beginning of the list. (the size will not change.) All "extra" elements at the end (however many occurrences of toRemove were in the list) should just be filled with 0. The method has no return value, and if the list has no elements, it should just have no effect.
Cannot use remove() and removeAll() from the ArrayList class.
The method signature is:
public static void removeAll(ArrayList<Integer> list, int toRemove);
The solution:
public static void removeAll(ArrayList<Integer> list, int toRemove) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) = toRemove) {
for (int j = i + 1; j < list.size(); j++) {
list.set(j - 1, list.get(j));
}
list.set(list.size() - 1, 0);
i--;
}
}
I understand the first for loop and the if statement well. Because one would want to iterate through the entire arrayList one-by-one and for each index with a number present in the arrayList check if it is, in fact the toRemovee integer. After this point I become lost.
Why another for loop?
Why are we taking the previous loops variable and adding 1 to it?
why within this second loop are we using the parameters "list" and using a set method?
why j - 1?
why list.get(j)?
Why after this second loop is over is there the line:
list.set(list. sise () - 1, 0) ?
why the i--?
There are a lot of moving parts and I would like to understand the logic.
Thank you
Firstly the if statement is assignment operation which isn't correct. You need to change the = to ==. I have explained each step in the code -
public static void removeAll(ArrayList<Integer> list, int toRemove) {
//start with the first number in the list until the end searching for toRemove's
for (int i = 0; i < list.size(); i++) {
//if the value at i is the one we want to remove then we want to shift
if (list.get(i) == toRemove) {
//start at the index to the right until the end
//for every element we want to shift it the element to its left (i == j - 1)
for (int j = i + 1; j < list.size(); j++) {
//change every value to whatever was to the right of it
//this will overwrite all values starting at the index where we found toRemove
list.set(j - 1, list.get(j));
}
//now that everything is shifted to the left, set the last element to a 0
list.set(list.size() - 1, 0);
//decrement to adjust for the newly shifted elements
// this accounts for the case where we have two toRemoves in a row
i--;
}
}
}
By the end of this function any value that matches toRemove is "removed" by shifting the arraylist to the left everytime the value is found and the last element will be set to 0.
Example
removeAll([1,2,3,4,5,5,6,7,8,5,9,5], 5)
Output
[1,2,3,4,6,7,8,5,9,0,0,0]
Please see the following to learn details (from minute 5:50 or 5:57)
https://www.youtube.com/watch?v=qTdRJLmnhQM
You need the second for loop ,to take all elements after the element you’ve removed it and shift it over one to the left so basically it’s filling up the space that is left empty from removing it so this is what this is doing.

Iterative Depth First Search To Find A String (2D Array)

I'm trying to create an iterative approach to a boggle game. The class contains fields for a 2d Array of Strings called "board" and has a 2d array of booleans called "haveVisit". The method that calls test 2 loops through the whole board, finding positions of the first character of the target string, then passes the coordinates into the test2 method, returning a list holding coordinates.
The return1Index method takes a 2D array coordinate at creates a int representative of the coordinates from a corresponding 1d array from it. The return2DIndex does the opposite and returns an int array holding the two coordinates.
public List<Integer> test2(int row1, int row2, String findMe){
String temp = findMe;
List<Integer> output = new ArrayList<Integer>();
if (board[row1][row2].charAt(0) != findMe.charAt(0))
return output;
haveVisit = new boolean[size][size];
int row = row1;
int column = row2;
output.add(return1DIndex(row, column));
haveVisit[row][column] = true;
//for each letter in the string
for(int j = 0; j < temp.length(); j++)
//for every column and row combination
for (int x = row - 1; x < row + 2 ; x++)
for (int y = column - 1; y < column + 2 ; y++)
//if index is valid and not visited
if (x > -1 && y > -1 && y < size && x < size && !haveVisit[x][y])
//if the output is the same size as string, return
if(output.size() == findMe.length())
return output;
//if the character in the board matches the char we're looking for
if(board[x][y].charAt(0) == temp.charAt(j))
{
haveVisit[x][y] = true;
output.add(return1DIndex(x, y));
//update row and column indices
row = x;
column = y;
}
}
}
return output;
}
For some reason this method works only 50% of the time. The method works fine with finding the letters when they're arranged left to right or top to bottom, but finding words from right to left or bottom to top never works except for one case: when you're searching for a string of length 1 or 2, where this method always works.
I have a working recursive solution but I wanted to try this way. Any thoughts as to why this wouldn't work?
Edit: Code now works from right to left, but still does not work when attempting to search upwards.
I don't know exactly what the problem is, but there are a few suspects:
You are updating row and column indices while checking their neighbors. This is like removing an element from an array while iterating through it: it's well defined, but has tricky semantics. I suggest either bailing out (greedy algorithm) or keeping a stack of matches (deeper search, requires saving stack of visited cells too).
The fors are missing opening braces, but the closing braces are there, suggesting missing code.
I'm not familiar with boggle, but isn't it possible for a letter to have two similar neighbors, like AXA? By just doing output.add(return1DIndex(x, y)); you may be outputting two ways to get the same letter. You may end up with output longer than findMe.
My suggestion is to follow a more standard format of depth-first search while you iron out the bugs. Wikipedia has a non-recursive pseudocode implementation, for example: https://en.wikipedia.org/wiki/Depth-first_search#Pseudocode .

Find multiple pairs (two pair and/or full house) in an array

int count = 1, maxCount = 0, elem = 0, maxElem = 0;
for (int i = 0; i < players; i++) {
for (int j = 1; j < 7; j++) {
if (arr[i][j] == arr[i][j - 1]) {
count++;
elem = arr[i][j - 1];
} else {
elem = 0;
count = 1;
}
if (count >= maxCount) {
maxCount = count;
maxElem = elem;
}
}
}
Not sure if it's 100% correct but this is how I managed to find the max element in this array and the number of its occurances.
This works only for one single (the max one) reoccuring element, though. What I need to do is to find all reoccuring elements. To be as precise as possible, I need to find whether there is either a two pair or a full house among those 7 js.
If someone doesn't know what those mean, a two pair is when there are two pairs of two equal numbers each. A full house is when there are two pairs, one of them consisting of two equal numbers, the other one of three equal numbers.
I need to find the biggest possible such pairs (both their values and numbers of occurance) amongst those 7 js.
I was thinking of using some sort of an array to store a pair if I find one but the problem is that I need to find such pairs for each and every i. And initializing an array in a for loop doesn't seem to be working out.
So how could I possibly find those pairs? Any advice or idea would be immensely appreciated!
To solve your problem and easier way to find 2 pairs or any thing else count your arr[][] into one dimension: arr[13] (I guess it's cards, 2 - Ace)
Then you can pass this array to check what ever you want like count pairs or full house and to know their numbers
Edit:
Now I paid attention about the first dimension is the player, so you can do the same with arr[players][13]

Checking symmetry in a grid with java

I need help with a game I'm doing:
The game is the following,
There are two players, 'B' and 'N'.
There is a grid of characters.
Both players take turn to place a char (B or N depending on who they are) on the grid.
Every time they place a char, I have to check whether there a symmetry is occuring. For example. There are differents types of symmetries. Horizontal and Vertical in every 2*2, 3*3 and 4*4 squares that contains the char that was just placed here. In the case of the 3*3 symmetry, the middle row or column does not take place in the symmetry.
I have done everything until now except the symmetries. I'm having some difficutly at doing them. I have an idea on how to do them but individually. Does any of you know how I could do the symmetries in one method only?
The java code for something similar to what you described for an n by n sized grid would go something like:
boolean isHorizontallySymmetrical(char[][] grid, int n){
int across = n / 2;
for(int i = 0; i < n; i++){
int right = 0
for(int left = 0; left < across; left++){
right = n - left - 1;
if(grid[i][left] != grid[i][right]){
return false;
}
}
}
return true;
}
A similar sort of thing would be needed for a vertical symmetry function.

Categories

Resources