Related
I'm trying to implement insertion sort and it works for one weird implementation but in reverse order. The same goes for another selection sort I was trying but it working the same way.
void insertionSort(ArrayList<T> genericAList) {
for (int n = 1; n < genericAList.size(); n++) {// go from start to end
// n=genericList.size
//n is primary index, j is secondary ind
for (int j = 0; j < n; j++) { // This sorts in descending order
//WHY DOES THIS NOT WORK?? for (int j = n-1; j>0; j--) {
if (genericAList.get(n).compareTo(genericAList.get(j)) == 1) {
T ncopy = genericAList.get(n);
genericAList.set(n, genericAList.get(j));
genericAList.set(j, ncopy);
}
}
//unsuccessfully trying to copy the array to reverse the order
ArrayList<T> copy = new ArrayList<>();
for (int i = genericAList.size() - 1; i >= 0; i--) { // start from end of old
copy.add(genericAList.get(i));
}
// genericAList=copy;
}
// return clone();
}
Note that compareTo is not guaranteed to return -1 or 1 for larger or smaller.
It returns 0 if they are the same, and then a number larger or smaller than 0 if they are different.
Imagine the pseudo-code for a primitive form of this - if we're comparing two numbers for instance we might do this:
public int compareTwoNumbers(x, y) {
return x - y;
}
So comparing 5 and 3 will give you -2 or 2 (for instance, depending on which way around they are).
The for loop should be int j = n; j > 0; j--, the == 1 should be > 0, and you're comparing/swapping the element at n when it should be j - 1.
Trying to merge 3 arrays into one so that the final array is in order.
Given
int[] a = {1,3};
int[] b = {2,4};
int[] c = {1,5};
Merge the arrays so that the final array d = {1,1,2,3,4,5}
Can't just concatenate them and then sort the d array because that would make the time complexity larger than Big-O(N).
This is what I got so far. Having problems with indexes out of bound exceptions:
public static void main(String[] args) {
// Sort these 3 arrays. The final array should be d = {1,1,2,3,4,5}
int[] a = {1,3};
int[] b = {2,4};
int[] c = {1,5};
int[] d = new int[a.length + b.length + c.length];
int i = 0;
int j = 0;
int k = 0;
int l = 0;
for (int iteration = 0; iteration <= d.length; iteration++){
if ((i != a.length || j != b.length) && a[i] < b[j]){
if (a[i] < c[k]){
// then a[i] is smallest
d[l] = a[i];
i++;
l++;
displayArrayContents(a,b,c,d,i,j,k,l);
}
else if (a[i] > c[k]){
// then c[k] is smallest
d[l] = c[k];
k++;
l++;
displayArrayContents(a,b,c,d,i,j,k,l);
}
else if (a[i] == c[k]){
d[l] = a[i];
i++;
l++;
d[l] = c[k];
k++;
l++;
displayArrayContents(a,b,c,d,i,j,k,l);
}
}
else if(b[j] < a[i]){
if (b[j] < c[k]){
// b[j] is smallest
d[l] = b[j];
l++;
j++;
displayArrayContents(a,b,c,d,i,j,k,l);
}
else if (b[j] > c[k]){
// c[k] is smallest
d[l] = c[k];
l++;
k++;
displayArrayContents(a,b,c,d,i,j,k,l);
}
else if (b[j] == c[k]){
d[l] = b[j];
j++;
l++;
d[l] = c[k];
k++;
l++;
displayArrayContents(a,b,c,d,i,j,k,l);
}
}
}
}
Your idea is correct and represents a O(n) solution. However, there are indeed some issues in your code, some of which will lead to out-of-bound exceptions:
You access c[k] without first making sure that k < c.length;
Even when you do test on length, you do it in a way that does not avoid such invalid access: (i != a.length || j != b.length) && a[i] < b[j] will still result in a[i] being accessed when i === a.length (notably when j != b.length);
The number of times the outer loop needs to iterate will often be wrong because sometimes (in case of equality) you store two values in the target array, which makes the array fill up faster than your loop foresees. In fact, the case of equality (like a[i] == c[k]) does not really need to be treated separately. If you treat it together with > (so: >=) the algorithm is still correct: the second (equal) value will be copied in the next iteration then;
Even if you fix the previous issue, your outer loop still makes one iteration too many; the for condition should be < d.length instead of <= d.length
Not problematic, but you have a lot of duplication in your code:
You could move the call to displayArrayContents(a,b,c,d,i,j,k,l); outside of the if construct, so it is always executed, which is what you really want;
As you always assign to d in the if construct, you could put that assignment "outside of the if" by using the ternary operator ? ... :;
Although tests like i != a.length work for the intended purpose, it is good practice to test like this: i < a.length.
Here is the code with the above taken into account:
import java.util.Arrays; // for easy output of arrays with Arrays.toString().
class Main {
public static void main(String[] args) {
// Sort these 3 arrays. The final array should be d = {1,1,2,3,4,5}
int[] a = {1,3};
int[] b = {2,4};
int[] c = {1,5};
int[] d = new int[a.length + b.length + c.length];
int i = 0;
int j = 0;
int k = 0;
for (int l = 0; l < d.length; l++) {
d[l] = i < a.length && (j >= b.length || a[i] < b[j])
? (k >= c.length || a[i] < c[k]
? a[i++]
: c[k++])
: (j < b.length && (k >= c.length || b[j] < c[k])
? b[j++]
: c[k++]);
// Uncomment this if you still need it:
//displayArrayContents(a,b,c,d,i,j,k,l);
}
System.out.println(Arrays.toString(d));
}
}
Output of last statement:
[1, 1, 2, 3, 4, 5]
See it run on repl.it.
Follow these steps:
Get the answer code from here: How to merge two sorted arrays into a sorted array?
Call that function on a and b, to get the resulting array ab
Call that function on ab and c, to get your result abc
You've called an O(n) function twice, so it's still O(n). BOOM.
The truth is, playing around with array indices is frustrating. If you can get those arrays as Queues or Itererators instead, just take() or next() the smallest value in each iteration and put it in the result list, it will be a lot cleaner.
You need to be clear on what changes with N. If you always have just three arrays and their size, or maximum size, changes with N, then almost any code which repeatedly selects the smallest number available from any of the three arrays, removes it, and appends it to the end of the result array, will be O(N). Your code for selecting the smallest number might be clumsy and expensive, but it is just a constant factor which does not change as N increases.
If the number of arrays to merge increases with N then you need to be more careful about how you select the smallest number available, and you will eventually end up with a sorting problem, which you can't do in linear time under the usual assumptions.
Typically external sorting will merge a large number of lists held on disk using a heap (e.g. http://www.geeksforgeeks.org/external-sorting/). This will be more efficient for merging a large number of lists at a time, but just gains you a constant factor,
Assuming this is java, array names are references to arrays and can be swapped like pointers in C / C++. This can be used to reduce the number of conditionals in the main merge loop, making the code a bit simpler, but at the cost of swapping. Empty array checks are done before the main merge loop. This method can be easily expanded to handle a 4 way or greater merge, which would otherwise require a lot of conditionals.
static int[] Merge(int[] a, int[] b, int[] c)
{
int[] d = new int[a.length + b.length + c.length];
int[] e; // temp used for swap
int i = 0;
int j = 0;
int k = 0;
int l = 0;
int t;
// empty array checks
if(0 == b.length){ // if b empty
if(0 == c.length){ // if b and c empty
c = a; // c = a
a = b; // a = b = empty
} else { // if b empty, c not empty
e = a; // swap a and b
a = b;
b = e;
}
} else { // else b not empty
if(0 == c.length){ // if c empty
e = c;
c = b; // shift c = b, b = a
b = a;
a = e; // a = empty
}
}
// main merge loop
while(i < a.length){ // 3 way merge
if(a[i] > b[j]){ // if b smaller swap
e = a;
a = b;
b = e;
t = i;
i = j;
j = t;
}
if(a[i] > c[k]){ // if c smaller swap
e = a;
a = c;
c = e;
t = i;
i = k;
k = t;
}
d[l++] = a[i++];
}
while(j < b.length){ // 2 way merge
if(b[j] > c[k]){ // if c smaller swap
e = b;
b = c;
c = e;
t = j;
j = k;
k = t;
}
d[l++] = b[j++];
}
while(k < c.length) // copy rest of c
d[l++] = c[k++];
return d;
}
Check this if logic looks simple to you.
Logic:
Identify the smallest element from 3 arrays and add it in mergeArray.
Also handle if all elements of array is covered( added in mergedArray), i.e. ignore that array from smallest number calculation.
import java.util.Arrays;
public class SortingAlgo {
public static void main(String[] args) {
int[] arr1 = {1,4,7,12,15,16,19,26,26, 29,35};
int[] arr2 = { 3,8,12,14,40, 44, 45};
int[] arr3 = {2,4,29, 30};
int[] merged = getMerged(arr1, arr2, arr3);
System.out.println(Arrays.toString(merged));
}
private static int[] getMerged(int[] arr1, int[] arr2, int[] arr3) {
int[] merged = new int[ arr1.length + arr2.length + arr3.length];
int i = 0; // Merged index
int i1 = 0, i2=0, i3=0; // for arr1, arr2, arr3
boolean i1Completed = false, i2Completed = false, i3Completed = false;
while(i1 < arr1.length || i2 < arr2.length || i3 < arr3.length) {
if(!i1Completed && (i2Completed || arr1[i1] <= arr2[i2]) && (i3Completed || arr1[i1] <= arr3[i3] )){
merged[i++] = arr1[i1++]; // arr1 element smallest
if(i1 == arr1.length)
i1Completed = true;
} else if(!i2Completed && (i1Completed || arr2[i2] <= arr1[i1] ) && ( i3Completed || arr2[i2] <= arr3[i3]) ){
merged[i++] = arr2[i2++];
if(i2 == arr2.length)
i2Completed = true;
} else if(!i3Completed && ( i2Completed || arr3[i3] <= arr2[i2] ) && ( i1Completed || arr3[i3] <= arr1[i1]) ){
merged[i++] = arr3[i3++];
if(i3 == arr3.length)
i3Completed = true;
}
}
return merged;
}
}
Output: [1, 2, 3, 4, 4, 7, 8, 12, 12, 14, 15, 16, 19, 26, 26, 29, 29, 30, 35, 40, 44, 45]
check output at replit
I'm trying to count the adjacent mines in my Array of tiles objects. The code works fine for any section of the grid within the boundary. let's assume it's a 10 by 10 array if I pick point 9,8 it will give me an array out of bounds exception. How can I make sure the Array will count the Adjacent mines on the edge of the array without giving me an ArrayOutOfBounds exception?
void countAdjacentMines(int x,int y) {
//Iterate through the array check if there is a mine
for (int i = 0; i < tiles.length; i++) {
for (int j = 0; j < tiles.length; j++) {
if ((tiles[i][j].getMine() == false)) {
int count = 0;
//Search adjacent tiles. at x,y
for (int p = x - 1; p <= x + 1; p++) {
for (int q = y - 1; q <= y + 1; q++) {
if (0 <= p && p < tiles.length && 0 <= q && q < tiles.length) {
if (tiles[p][q].getMine()==true)
count++;
}
tiles[p][q].setCount(count);
}
}
}
} // end for loop rows
} // end for loop columns
} // end countAdjacentMines
Create a function
int hasMine (int x, int x)
that returns 1 when (x,y) holds a mine,
or 0 if either it doesn't or (x,y) is not a valid cell (it is also useful
to have a boolean valid (int x, int y) function).
Then, just do:
totalMines = hasMine(x+1,y+1) + hasMine(x+1, y) + hasMine(x+1, y-1) + .... + hasMine (x-1,y-1) // 8 hasMine() calls.
The problem is due to
if (0 <= p && p < tiles.length && 0 <= q && q < tiles.length) {
if (tiles[p][q].getMine()==true)
count++;
}
tiles[p][q].setCount(count);
where the last statement isn't guarded by the test that p and q are within bounds.
But I think that the entire method isn't right: either you need to iterate the entire board and count, or you access a single place (x,y) and do the count for this one.
I need to figure out how to turn the 3x3 array
{{7,2,3},
{0,4,8},
{5,6,1}}
into a 9x9 array where each 3x3 section is the original array o, but each value n is n+(9*c) where c is the corresponding section. In other words, section 0, 0 (top left) should have each of its values changed to originalValue+(9*7) since the top-left section of the original array is 7. Similar with the bottom-right, but the formula would be originalValue+(9*1) since the bottom-right section of the original array is 1.
The new array should look like (just including the two sections mentioned)
{{70,65,66,0,0,0,0,0,0},
{63,67,70,0,0,0,0,0,0},
{68,69,64,0,0,0,0,0,0},
{00,00,00,0,0,0,0,0,0},//leading zeros added for easy legibility
{00,00,00,0,0,0,0,0,0},
{00,00,00,0,0,0,0,0,0},
{0,0,0,0,0,0,16,11,12},
{0,0,0,0,0,0,09,13,17},
{0,0,0,0,0,0,14,15,10}}
Now here is the hard part: I then need to repeat the process, but using this 9x9 array as the original array to get a 27x27 array, and then repeat it even more times to get a bigger array each time (81x81 then 243x243, etc.).
I have been able to get the method addAllValues() but I am stuck from going further.
public static int[][] addAllValues(int[][] data, int value2){
int value = value2 * 9;
int[][] temp = data.clone();
int[][] newData = temp.clone();
for (int i = 0; i < temp.length; i++) {
for (int j = 0; j < temp[0].length; j++) {
newData[i][j] = temp[i][j] + value;
}
}
return newData;
}
Can anyone help me with this? Thanks in advance!
Here is what I have tried:
public static int[][] gen(int amount) {
if (amount == 0) {
return normal;
} else {
int[][] newArray = gen(amount-1);
int[][] temp = new int[newArray.length*3][newArray.length*3];
int[][][][] newArrays = {{addAllValues(newArray,7),addAllValues(newArray,2),addAllValues(newArray,3)},{addAllValues(newArray,0),addAllValues(newArray,4),addAllValues(newArray,8)},{addAllValues(newArray,5),addAllValues(newArray,6),addAllValues(newArray,1)}};
for (int i = 0; i < temp.length; i++) {
for (int j = 0; j < temp.length; j++) {
int x=0,y=0;
if (0 <= i && i < 3){
x = 0;
} else if (3 <= i && i < 6){
x = 1;
} else if (6 <= i && i < 9){
x = 2;
}
if (0 <= j && j < 3){
y = 0;
} else if (3 <= j && j < 6){
y = 1;
} else if (6 <= j && j < 9){
y = 2;
}
temp[i]
[j] = newArrays[x]
[y]
[i]
[j];
}
}
return temp;
}
}
Ok this is pretty basic.
You have a square matrix A.
[a b c]
A = [e f g]
[h i j]
You copy the matrix 3 times to the right (horizontally) to get [A A A], and then you copy the strip 3 times to the bottom (vertically) to get a square strip of matrices
[A A A]
B = [A A A]
[A A A]
The new matrix is 3 times bigger per dimension, or totally 9 times bigger (per "area"). Now what you need to do is modify each submatrix -- add the corresponding element from the original matrix. You need to find the indices of the submatrix (the indices of the subsections), and use those same indices in the original matrix to get the corresponding scalar.
[9*A(0,0)+A 9*A(0,1)+A 9*A(0,2)+A]
[9*A(1,0)+A 9*A(1,1)+A 9*A(1,2)+A]
[9*A(1,0)+A 9*A(1,1)+A 9*A(1,2)+A]
The last link we need to set is to know which element in the new matrix B corresponds to which section.
B is 3 times bigger, e.g. B[0..8, 0..8] so if we divide the indices of element in B by 3 (integer division) we get it's section and this the indices of the scalar in A.
We say an element B(r,c) lays in section (i,j)=(r/3, c/3) and thus this element shall be modified with A(i,j). This last sentence pretty much sums it up.
I have an exercise in which I have to sort an array in the following way:
the numbers that divide 4 with no remainder will be the first in the array (e.g 4,8,12,16).
the numbers that divide 4 with remainder of 1 will be the second in the array (1,5,9).
the numbers that divide 4 with remainder of 2 will be the third in the array (2,6,10).
the numbers that divide 4 with remainder of 3 will be last in the array.
For example, the following array:
int []a={1,7,3,2,4,1,8,14}
will be:
4 8 1 1 2 14 3 7
the order within the groups does not matter.
I have found a solution which works on O(n) time complexity and O(1) space complexity.
However, it is ugly and moves on the array 3 times. I would want a more elegant solution.
This is my code:
int ptr=a.length-1; int temp=0, i=0;
while (i<ptr){
//move 3 remained to the end
if (a[i] % 4==3){
temp=a[ptr];
a[ptr]=a[i];
a[i]=temp;
ptr--;
}
else
i++;
}
i=0;
while (i<ptr){
if (a[i]%4==2)
{
temp=a[ptr];
a[ptr]=a[i];
a[i]=temp;
ptr--;
}
else
i++;
}
i=0;
while (i<ptr){
if (a[i]%4==1)
{
temp=a[ptr];
a[ptr]=a[i];
a[i]=temp;
ptr--;
}
else
i++;
}
Important to know:
I don't want time complexity worse than O(n), and space complexity worse than O(1).
Since O(3 * N) is O(N), you only need to loop through the array three times:
Move the elements e % 4 == 0 to the front, swapping elements along the way;
Move the elements e % 4 == 1 to the front, swapping elements along the way;
Move the elements e % 4 == 2 to the front, swapping elements along the way;
The elements that e % 4 == 3 will be at the end after this.
Example:
public static void main(String args[]) {
int[] a = { 1, 7, 3, 2, 4, 1, 8, 14 , 9};
int current = 0;
for (int i = 0; i < 3; i++) {
for (int j = current; j < a.length; j++) {
if (a[j] % 4 == i) {
int b = a[j];
a[j] = a[current];
a[current] = b;
current++;
}
}
}
System.out.println(Arrays.toString(a));
}
Just use a comparator and make use for the very efficient internal sort algorithm.
Arrays.sort(a, new Comparator() {
public int compare(int a, int b) {
if(a%4 == b%4) {
if(a < b) return -1;
if(a > b) return 1;
return 0;
} else {
if(a%4 < b%4) return -1;
if(a%4 > b%4) return 1;
return 0;
}
}
});
You can use up more memory. This is not correct, but I will still put it.
int modulusLength = 4;
List<Integer> array[] = new List<Integer>[modulusLength];
for(int i = 0; i < modulusLength; i++)
array[i] = new ArrayList<Integer>;
for(int i = 0 ; i < a.length; i++)
array[a[i]%modulusLength].put(a[i]);
int counter = 0;
for(int i = 0 ; i < array.length; i++)
for(int j = 0; j < array[i].size; j++)
{
a[counter] = array[i].get(j);
counter++;
}
Horrible and scary, but was fun to write. And it works :)