Java 2d array matrix program - java

int even = 0;
int odd = 0;
for(i=0;i<5;i++){
for(j=0;j<5;j++){
if(j%2>=i) // I think the problem is this
even += twoD[i][j];
else
if(i%2!>=j) // I think the problem is this
odd += twoD[j][i];
}
}
System.out.println("The sum of the even elements above the diagonal is: "+even);
System.out.println("The sum of the odd elements below the diagonal is: "+odd);
This is the code I am working with. The problem is it doesn't display the real sum of the elements above and below as I'd want in a diagonal. The matrix is basically randomized so I had to check it everytime to verify the sum.

For the elements above the diagonal j > i (index of column is always greater than that of the row); for the elements below j < i.
Then the loops may be optimized slightly to provide j > i and swapping indexes for elements below the matrix diagonal:
int even = 0;
int odd = 0;
for(int i=0; i<twoD.length; i++) {
for(int j=i + 1; j<twoD[i].length; j++) {
if(twoD[i][j] %2 == 0) {
even += twoD[i][j];
}
if(twoD[j][i] %2 != 0) { // swap indexes below diagonal
odd += twoD[j][i];
}
}
}

Exactly as you've thought, the conditions are incorrect. Actually I'm not sure what was the logic behind them.
What you need to do is to find whether given number is above or below diagonal. You can do that by comparing indicies themselves - j>i and j<i.
Only then you need to check if a given number (not index) is odd or even - twoD[i][j] % 2 == 0.
Something like so should get the job done:
for(i=0;i<5;i++){
for(j=0;j<5;j++){
if(j>i && twoD[i][j]%2==0){
even += twoD[i][j];
}
if(j<i && twoD[i][j]%2!=0){
odd += twoD[i][j];
}
}
}

Related

How to implement merge sort without recursion

The arrays are always the size of powers of 2, and it can't be recursive.
If I've made any errors in asking my question this is my first time asking a question. Bear with me please.
The plan is to place markers in powers of two then loop through and place the ordered numbers into an array then putting them back in the array. Then should be placed into the original array in the groups that they were placed split into. Gradually getting bigger until the whole array is sorted.
public static void MergeSortNonRec(long[] a) {
//======================
//FILL IN YOUR CODE HERE
//======================
System.out.println(a.length); // print statement
if (a == null)
return;
int subArray1 = 0;
int subArray2 = 1;
int increment = 0;
int swapCounter = 0;
for (int i = 1; i <= a.length; i *= 2) {
// this loop determines the current size of the sub array
increment = i;
subArray1 = 0;
subArray2 = 0;
swapCounter = 0;
while (subArray2 <= a.length) {
// this will loop until we reach the end of the array
subArray2 += increment;
long[] spareArray = new long[2 * i];
swapCounter = 0;
while (swapCounter <= spareArray.length) {
System.out.println(subArray1 + " " + subArray2); // print statement
if (a[subArray1] < a[subArray2]) {
spareArray[swapCounter] = a[subArray1];
swapCounter++;
subArray1++;
} else
if (a[subArray1] > a[subArray2]) {
spareArray[swapCounter] = a[subArray2];
swapCounter++;
subArray2++;
} else
if (a[subArray1] == a[subArray2]) {
spareArray[swapCounter] = a[subArray1];
swapCounter++;
subArray1++;
System.out.println(swapCounter + " " + subArray1); // print statement
spareArray[swapCounter] = a[subArray1];
swapCounter++;
subArray2++;
}
} // this creates an array of the ordered elements
while (swapCounter == spareArray.length) {
subArray1 -= swapCounter / 2;
subArray2 -= swapCounter / 2;
// now the sub array pointers are back to the values they started at
int spareArrayPointer = 0;
for (; subArray1 <= subArray2; subArray1++) {
a[subArray1] = spareArray[spareArrayPointer];
spareArrayPointer++;
} // this places the values in the spare array into the original array
subArray1 -= spareArrayPointer;
spareArrayPointer = 0;
// takes the first pointer back to where it started
}
subArray1 += increment;
subArray2 += increment + increment;
} // end subArray2 <= a.length loop
} // end 2*i loop
} //MergeSortNonRec()
A non-recursive implementation of merge sort could still be based on top down merge sort, using a stack to push and pop pairs of indexes.
A more common implementation of non-recursive merge sort is bottom up, where an array of n elements is treated as n "sorted" runs of size 1 (since their size is 1, they can be considered sorted), then for each merge "pass", merge even and odd runs, which doubles the run size on each pass. Repeat until run size >= array size.
Wiki example. This example could be optimized by swapping A and B after each pass to change the direction of merge with each pass and avoid the copy back except for the lass pass (or determine number of passes in advance, and swap in place to start with run size = 2 before doing the merge passes).
https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation

Maximum Sum Subarray O(n) not Kadane's

I'm reading Cormen's "Introduction to Algorithms".
For the linear algorithm for Max Sum Subarray problem I came up with my own solution. Didn't check existing one (Kadena's) before implementing.
Now I'm testing it with different test scenarios and always have better results than Kadena's. I don't believe in such a luck, but can't find what have I missed. Could you take a look whether it is a working solution?
public void findMaxSubarray(Number[] numbers) {
int maxSum = Integer.MIN_VALUE;
int left = 0;
int right = numbers.length - 1;
int i = 0;
int j = i + 1;
int sum = numbers[i].intValue();
while (i < numbers.length) {
if (maxSum < sum) {
maxSum = sum;
left = i;
right = j - 1;
}
if (j >= numbers.length)
return;
sum = sum + numbers[j].intValue();
if (sum <= 0) {
// ignoring "first" negative numbers. shift i to first non-negative
while (numbers[j].intValue() <= 0) {
if (maxSum < numbers[j].intValue()) {
maxSum = numbers[j].intValue();
left = j;
right = j;
}
if (++j >= numbers.length)
return;
}
i = ++j;
sum = 0;
}
j++;
}
System.out.println(String.format("Max subarray is %d, [%d; %d]", maxSum, left, right));
}
Update
The idea of code is to keep in track only one subarray, and adding to its' tail numbers, when numbers are that low that sum becomes negative - set beginning of array after the tail.
Additionally negative items in the beginning are being ignored. head of subarray is just shifted forward.
Everytime sum appears to be maximum - maxSum and limits are updated.
shift i() --to first non negative number
from j = i+1 up to N.length
sum + N[j]
if sum <= 0
i = j+1
if N[i] < 0
shift i()
sum = 0
I think your algorithm is basically sound, but it has two bugs that I can see:
On the input 1 -2 10 3, it will skip over the 10 and output 3. I think you can fix this by changing i = ++j; to i = j;.
In 2 different places you return if j goes past the end, which will cause no output to be produced at all! (This will happen if, e.g., a long list of negative numbers appears at the end of the list.)
Also I don't expect it to be faster (or slower, for that matter) than Kadane's. Summing two numbers is a fast operation, as fast as copying one variable to another, which is what you are doing when you shift the start of the subarray.

Randomly filling a 2d boolean array with equal amounts of both values

I'm trying to find a way to fill a 2d array of length n with boolean values randomly. The array must have an equal amount of each value if n is even, and if n is odd the extra value must be the same boolean each and every time (doesn't matter which one). Any tips on how to do this in Java? I'm currently shuffling arrays that I make with equal amounts of both values, but this isn't truly random because there will always be n/2 (or n/2+1 and n/2-1 for the odd ns) of each value.
Any advice?
Given your requirements, filling the array with the amount you need, then shuffling it, is a good solution.
Make sure to use a truly random shuffling algorithm, such as the Fisher-Yates shuffle, not the "swap a random pair a bunch of times" method. If you're using Collections.shuffle or similar, you don't need to worry about this.
Adapting the Fisher-Yates shuffle to a 2D array is probably the simplest approach.
boolean[][] array = new boolean[rows][cols];
boolean alternating = false;
Random random = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int k = random.nextInt(i * cols + j + 1);
int swapRow = k / cols;
int swapCol = k % cols;
boolean tmp = array[swapRow][swapCol];
array[swapRow][swapCol] = alternating;
array[i][j] = tmp;
alternating = !alternating;
}
}
This is pretty much a verbatim implementation of http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_.22inside-out.22_algorithm , except that we're filling the array as we go with falses and trues.
A different approach might be to randomise the position you are placing the next value rather than the value itself. You know ahead of time exactly how many of each value you are placing.
Something like:
List<Integer> indicesList = IntStream.range(0, n * n).collect(Collectors.toList());
Collections.shuffle(indicesList);
indicesList.stream().forEach(n -> array[n % size][n / size] = (n % 2 == 0));
By my understanding that should give you completely random placement of your values and an equal number of each.
Here's a real simple solution a coworker came up with. It looks to me like it would work and be truly random (please let me know if not, I have terrible intuition about that kind of thing), although it's definitely ugly. Would be pretty efficient compared to a shuffle I imagine.
public boolean[][] generateRandom2dBooleanArray(int length) {
int numFalses = (length*length)/2;
int numTrues = (length*length)/2;
if ((length*length)%2!=0) numTrues++;
boolean[][] array = new boolean[length][length];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (Math.random() > 0.5) {//Or is it >= 0.5?
if (numTrues >= 0) {
array[i][j] = true;
numTrues--;
} else {
//Since boolean arrays are false by default, you could probably just break here to get the right anser, but...
array[i][j] = false;
numFalses--;
}
} else {
if (numFalses >= 0) {
array[i][j] = false;
numFalses--;
} else {
array[i][j] = true;
numTrues--;
}
}
}
}
}
return array;
}

Sub-Array Max Sum

I'm looking over an assignment that I finished a few days ago and realized I'm not supposed to use constants. The assignment is the well-known "find the largest sum of a sub-array of integers both positive and negative recursively using a divide and conquer approach" problem. My algorithm works, but a part of it uses a constant in order to figure out the largest sum of sub-arrays that include the middle of the array.
Here's the relevant code:
lfSum = Integer.MIN_VALUE;
sum = 0;
// Sum from left to mid
for (int i = mid; i >= LF; i--) {
sum += array[i];
if (sum > lfSum) {
lfSum = sum;
if (lfSum > lfMax) {
lfMax = lfSum;
}
}
}
rtSum = Integer.MIN_VALUE;
sum = 0;
// Sum from mid to right
for (int j = mid+1; j <= RT; j++) {
sum += array[j];
if (sum > rtSum) {
rtSum = sum;
if (rtSum > rtMax) {
rtMax = rtSum;
}
}
}
// Largest sum spanning whole array
midMax = lfSum + rtSum; // midMax = leftMid + midRight;
What this does is it loops through each half of the entire array and checks to see if the sum is larger than the smallest integer possible in case the entire array is negative. If it is, it sets that side's max sum to sum's value. If that value is larger than what one of the recursive calls returned (lfMax or rtMax), set the respective side's recursive value to it.
Like I said earlier, this works perfectly well, but I'm not supposed to be using "Integer.MIN_VALUE". Is there another way around this? Obviously I could initialize lfSum/rtSum to the numerical value of Integer.MIN_VALUE, but I'd like to know if there are any other options.
I've tried removing rtSum/lfSum and just comparing sum to the recursive values, and initializing lfSum/rtSum to 0, but both did not work correctly. Thanks for taking the time to read this!
You can initialize lfSum as null:
Integer lfSum = null;
And modify the if condition like this:
if (lfSum == null || (lfSum != null && sum > lfSum.intValue())) {
lfSum = sum;
if (lfSum > lfMax) {
lfMax = lfSum;
}
}
Similar strategy applies to rtSum.

How to compare two arrays of integers order-insensitively

I want Java code that can compare in this way (for example):
<1 2 3 4> = <3 1 2 4>
<1 2 3 4> != <3 4 1 1>
I can't use hashmap table or anything; just pure code without library.
I know there are two ways.
sort them and compare the array index by index
use two for loops and compare the outer index with the inner index. I have been trying with this but still not working:
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(a[i] != a[j] && j == n)
return false;
}
}
return true;
anything wrong with the code ? thanks
Sort & compare. You can't get the complexity better than that, and any "improvement" that you do on the speed comes at the risk that your code will be wrong.
[edit] Actually.... if you know your numbers are relatively small (e.g. say: the arrays only contain numbers between 0 and 1000), that there's an alternative in O(n). Something like this (sorry if the syntax is wrong, I didn't use java lately):
int count[1001]; // already intialized to 0
for(int i=0;i<n;i++){ count[a[i]]++; count[b[i]]--;}
bool arrays_identical = true;
for(int i=0;i<=1000 && arrays_identical; i++)
arrays_identical &= count[i]==0;
Disclaimer: this code doesn't contain "sanity checks" (i.e. the arrays are really of length "n", the numbers are in the prescribed interval) - it's only to illustrate the principle.
Arrays.sort(a);
Arrays.sort(b);
return Arrays.equals(a, b);
Since this is homework, I'm going to guess that a simple quadratic solution (which your original attempt is), is fine. In that case, you can do something like this:
int count(int[] nums, int x) {
int count = 0;
for (int num : nums) {
if (num == x) count++;
}
return count;
}
boolean equals(int[] arr1, int[] arr2) {
if (arr1.length != arr2.length) return false;
for (int x : arr1) {
if (count(arr1, x) != count(arr2, x)) return false;
}
return true;
}
This sacrifices speed for clarity: it's obviously correct!!
Tips
Use for-each whenever applicable; it always read to better readability
Helper functions improve both readability and reusability!
Before you actually start a more computationally complex solution, you can run a fast O(n) test to see if the arrays are the same. There are times when this this will result in a false positive, and you can use more computationally intensive means to investigate further. If it returns false, you can be assured that the arrays are different.
The basic approach is to do a cummulative XOR between the ith elements of the two arrays. If the resulting XOR is non-zero then you know that the two arrays are different. If the XOR is zero, they might be the same, but more work is needed to confirm.
int c_xor = 0; // XOR accumulator
for (int i = 0; i < n; ++i)
c_xor ^= arr1[i] ^ arr2[i];
// They're different if c_xor != 0; the might be the same if c_xor == 0
return c_xor == 0;
I think it would be sensible to check that the lengths of both arrays are equal before doing any iterating. It's a cheap way to opt out of hard work early, and it fixes the following type of failure for the second approach you mention:
{1, 2, 3} seen as equal to {4, 3, 2, 1}
This is a O(n^2) problem. No other solution is faster than comparing the two arrays directly.
The Virgil's solution is cool, except for the fact that it is not really O(n) performance. It is really O(n+1000) performance. The array comparison second time to set the boolean variable is costly and backfires in small arrays.
The solution you wrote is the best except for a bugs.
Here is the error corrected version.
boolean[] matchedPositions = new boolean[n];
for(int k = 0; k < n; k++
{
matchedPositions[k] = false;
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(matchedPositions[j] == false && a[i] == a[j])
{
matchedPositions[j] = true;
break;
}
if(j == n - 1)
{
return false;
}
}
}
return true;
In this case if in case the integer matches then the inner loop will break and set or flag the matched position. This is required for arrays with duplicate entries, this will avoid two entries in left array matching with one entry in the right array.
If in case the match did not happen, which is identified by j == n - 1, you will return false.
Since we are expecting a default value of false in boolean its better to flag initialize it.
In reality, this solution has O(n log n + n) performance penalty. Sort and compare has a performance penalty of O(n^2 + n) too. Sort has O(n^2) performance and one loop for checking. But sorting changes the contents of the array and this does not.
if you take one array as 1,2,3,4,3,1,2,4 then the solution is in this way.
2n = total number of integers : 8
//program
int i, j, n = 4;
for(i = 0; i < n; i++)
for(j = n; j < 2n; j++)
{
if( a[i] != a[j])
{
j++;
}
else
{
i++; exit();
}
}
if (i == n)
{ //They both are equal;
}
else if(i != n)
{
//They both are not equal;
}
If it is not working please comment on it.
Thank You.
Here is a fix for the code that you posted.
for(int i = 0; i < n; i++)
{
int j;
for(j = 0; j < n; j++)
{
if(a[i] == b[j]) break;
}
if (j == n) return false;
}
return true;
That algorithm is going to break done for arrays that contain duplicates, however. For example, the array {1, 1, 2, 3} will be found as a match to the array {1, 2, 2, 3}.
I would highly recommend that you implement a sort-and-compare algorithm instead.

Categories