Related
I am relatively new to coding and I am starting a review of leetcode, and floundered on a question...looking at the 3ms-runtime solution leetcode supplied I am confused about the function of the 4th line in method findDisappearedNumbers.
My assumption is that for the 0 index running 'arr[nums[i] - 1]++' would assign 4 to arr[0], but it assigns 1. Can someone help me understand what is happening?
The result of running this code is: [1, 2, 2, 1, 0, 0, 1, 1]
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
public class FindAllNumbersDisappearedInAnArray {
public static void main(String[] args) {
int[] arr = new int[]{4,3,2,7,8,2,3,1};
/*System.out.println(findDisappearedNumbers(arr));*/
System.out.println(Arrays.toString(findDisappearedNumbers(arr))); //user added for examing code
}
public static int[] /*List<Integer>*/ findDisappearedNumbers(int[] nums) { //int[] was user added for examing code
List<Integer> list = new ArrayList<>();
int[] arr = new int[nums.length];
for(int i = 0; i < nums.length; i++) {
arr[nums[i] - 1]++; //What is happening here?
}
for(int i = 0; i < nums.length; i++) {
if(arr[i] == 0) {
list.add(i+1);
}
}
/*return list;*/
return arr; //user added for examing code
}
}
(The question was:
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.)
In the expression arr[nums[i] - 1]++;, nums[i] - 1 determines the index of a value in arr[], not the value which should be wirtten into it. Than the found value is incremented by one, because of ++.
Knowing that the default value of an int is 0, so when arr[] is initialized it contains only zeros, we can see, that after the first iteration of the first for loop arr[] is [0, 0, 0, 1, 0, 0, 0, 0]. We see a 1 on the 4.th (starting from 1) position of arr[], which means that one 4 has been found in nums[].
If you add System.out.println(Arrays.toString(arr) after the first for loop you will see following output: [1, 2, 2, 1, 0, 0, 1, 1]. According to the logic described above, it means, that nums[] contains one 1, two 2s, two 3s, one 4, no 5, no 6, one 7 and one 8.
I've got to a dead end in the homework working on sorting a integers two-dimensional array.
The instructions are to create a function that takes a two-dimensional int array
(not necessarily a matrix) and sort the Outer array according to the sum of the inner arrays. in other words, in the first index of the array should be the inner array with the lowest sum.
Example -
input - int[][] array = {{2, 4, 1,9,9,9,9}, {6, 8}, {7, 3, 6, 5, 1}};
output - array = {{6, 8}, {7, 3, 6, 5, 1}, {2, 4, 1,9,9,9,9}};
My logic so far is creating a new one dimensional array that will include the sum
of each of the inner arrays from the main array.
and work with the sorting according to it.
public static int[] arraysCalculator(int[][] arr) {
int[] sums = new int[arr.length];
int sum= 0;
for(int i = 0; i < arr.length; i++)
{
for(int j = 0; j < arr[i].length; j++)
{
sum += arr[i][j];
}
sums[i] = sum;
sum = 0;
}
You can easily sum an int[] by streaming it and then calling sum(). From there, it's just a matter of calling Arrays.sort with a comparator that compares this sum:
Arrays.sort(array, Comparator.comparingInt(a -> Arrays.stream(a).sum()));
You got like one third. What you need now:
after creating that first array sums that contains the sums of the "inner" arrays, you simply create an exact copy of that array, like originalSums
then, you sort the content of sums
Example: say sums and originalSums are [ 12, 3, 7]. After sorting you get:
originalSums: [ 12, 3, 7]
sums: [ 3, 7, 12]
The thing is: by looking at both arrays, you can decide how to swap the inner arrays to match the order that sums shows you now.
In the above example, you notice that 12 has the original index 0. After sorting, its index is 2. So you know that you have to "swap" the inner arrays for 0 and 2. You can also deduce that 3 should go to index 0, and 7 to index 2.
Of course, it is still a bit of work to ensure that the swapping works out (like you better not swap any index twice).
The most basic way to get the whole thing going is to simply look at just one index at a time (like you do some sort of bubble sort).
Long story short: there are many different ways to solve this. I suggest you start with the easiest path.
In addition to the other answers who did a great job explaining the theory and laying the ground work for solving your assignment, here is a full working example (with detailed documentation on what each thing does and why) that will hopefully be of some assistance:
/**
* This method will sort the inner arrays of a given two dimensional array
* from lowest to highest value according to the sum of it's elements.
*/
private static int[][] arrayCalc(int[][] arr)
{
/*
* We're working with a TreeMap here because this type
* of map is allowed to have duplicate key entries
*/
java.util.Map<Integer, Integer[]> map = new java.util.TreeMap<>();
/*
* This value represents the largest inner array
* size found in 2d array passed as parameter
*/
int largestSize = 0;
for (int[] inner : arr) {
/*
* Convert the inner array to an array of Integer
* objects so it can be placed inside a map
*/
Integer[] integers = IntStream.of(inner).boxed().toArray(Integer[]::new);
map.put(IntStream.of(inner).sum(), integers);
/*
* Check if this inner array has a larger value
* then the largest array we processed so far
*/
if (inner.length > largestSize) {
largestSize = inner.length;
}
}
int[][] result = new int[map.size()][largestSize];
/*
* Iterate over the map and copy it's values which are represented
* as Integer arrays into inner arrays of our return value
*/
java.util.Iterator<java.util.Map.Entry<Integer, Integer[]>> iter = map.entrySet().iterator();
for (int i = 0; i < result.length && iter.hasNext(); i++)
{
java.util.Map.Entry<Integer, Integer[]> entry = iter.next();
/*
* We can just return our value as an array of Integer objects
* but for the sake of this exercise we will convert it to a
* primitive 2D int array so it's consistent with our method parameter
*/
Integer[] integers = entry.getValue();
result[i] = java.util.Arrays.stream(integers).mapToInt(Integer::intValue).toArray();
}
return result;
}
public static void main(String[] args)
{
int[][] array = {{2, 4, 1,9,9,9,9}, {6, 8}, {7, 3, 6, 5, 1}};
int[][] result = arrayCalc(array);
for (int[] iResult : result) {
System.out.println(Arrays.toString(iResult));
}
}
Output
[6, 8]
[7, 3, 6, 5, 1]
[2, 4, 1, 9, 9, 9, 9]
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Right now I'm trying to write a function that takes an array and an integer n, and gives a list of each size n combination (so a list of int arrays). I am able to write it using n nested loops, but this only works for a specific size of subset. I can't figure out how to generalize it to work for any size of combination. I think I need to use recursion?
This is the code for all combinations of 3 elements, and I need an algorithm for any number of elements.
import java.util.List;
import java.util.ArrayList;
public class combinatorics{
public static void main(String[] args) {
List<int[]> list = new ArrayList<int[]>();
int[] arr = {1,2,3,4,5};
combinations3(arr,list);
listToString(list);
}
static void combinations3(int[] arr, List<int[]> list){
for(int i = 0; i<arr.length-2; i++)
for(int j = i+1; j<arr.length-1; j++)
for(int k = j+1; k<arr.length; k++)
list.add(new int[]{arr[i],arr[j],arr[k]});
}
private static void listToString(List<int[]> list){
for(int i = 0; i<list.size(); i++){ //iterate through list
for(int j : list.get(i)){ //iterate through array
System.out.printf("%d ",j);
}
System.out.print("\n");
}
}
}
This is a well-studied problem of generating all k-subsets, or k-combinations, which can be easily done without recursion.
The idea is to have array of size k keeping sequence of indices of elements from the input array (which are numbers from 0 to n - 1) in increasing order. (Subset then can be created by taking items by these indices from the initial array.) So we need to generate all such index sequences.
First index sequence will be [0, 1, 2, ... , k - 1], on the second step it switches to [0, 1, 2,..., k], then to [0, 1, 2, ... k + 1] and so on. The last possible sequence will be [n - k, n - k + 1, ..., n - 1].
On each step, algorithm looks for the closest to the end item which can be incremented, increments it and fills up items right to that item.
To illustrate, consider n = 7 and k = 3. First index sequence is [0, 1, 2], then [0, 1, 3] and so on... At some point we have [0, 5, 6]:
[0, 5, 6] <-- scan from the end: "6" cannot be incremented, "5" also, but "0" can be
[1, ?, ?] <-- "0" -> "1"
[1, 2, 3] <-- fill up remaining elements
next iteration:
[1, 2, 3] <-- "3" can be incremented
[1, 2, 4] <-- "3" -> "4"
Thus, [0, 5, 6] is followed by [1, 2, 3], then goes [1, 2, 4] etc.
Code:
int[] input = {10, 20, 30, 40, 50}; // input array
int k = 3; // sequence length
List<int[]> subsets = new ArrayList<>();
int[] s = new int[k]; // here we'll keep indices
// pointing to elements in input array
if (k <= input.length) {
// first index sequence: 0, 1, 2, ...
for (int i = 0; (s[i] = i) < k - 1; i++);
subsets.add(getSubset(input, s));
for(;;) {
int i;
// find position of item that can be incremented
for (i = k - 1; i >= 0 && s[i] == input.length - k + i; i--);
if (i < 0) {
break;
}
s[i]++; // increment this item
for (++i; i < k; i++) { // fill up remaining items
s[i] = s[i - 1] + 1;
}
subsets.add(getSubset(input, s));
}
}
// generate actual subset by index sequence
int[] getSubset(int[] input, int[] subset) {
int[] result = new int[subset.length];
for (int i = 0; i < subset.length; i++)
result[i] = input[subset[i]];
return result;
}
If I understood your problem correctly, this article seems to point to what you're trying to do.
To quote from the article:
Method 1 (Fix Elements and Recur)
We create a temporary array ‘data[]’ which stores all outputs one by
one. The idea is to start from first index (index = 0) in data[], one
by one fix elements at this index and recur for remaining indexes. Let
the input array be {1, 2, 3, 4, 5} and r be 3. We first fix 1 at index
0 in data[], then recur for remaining indexes, then we fix 2 at index
0 and recur. Finally, we fix 3 and recur for remaining indexes. When
number of elements in data[] becomes equal to r (size of a
combination), we print data[].
Method 2 (Include and Exclude every element)
Like the above method, We create a temporary array data[]. The idea
here is similar to Subset Sum Problem. We one by one consider every
element of input array, and recur for two cases:
The element is included in current combination (We put the element in data[] and increment next available index in data[])
The element is excluded in current combination (We do not put the element and do not change index)
When number of elements in data[] become equal to r (size of a
combination), we print it.
For my summer Java class, I'm working on a program that detects whether the elements in an array are a magic square. I'm not entirely sure how to properly iterate through the array to be able to calculate the total of the separate columns and rows to determine if the array is a magic square. We were given the code for the sum of the down diagonal, but I'm unsure how to approach the up diagonal, rows and columns. Here is a snippet of my code so far.
public class MagicSqaure
{
public static void main(String[] args)
{
int[][] array =
{
{2, 7, 6},
{9, 5, 1},
{4, 3, 8}
};
public static int getSumOfDownDiagonal(int[][] array)
{
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[i][i];
}
return total;
}
Since it is a class, I can only provide help on how to accomplish traversing through the rows, columns and up diagonal, but providing **no code at all*. It's up to you to do the right implementation, otherwise you're not learning but copying/pasting/becoming a zombie coder.
To traverse each row, go through the elements of your array of arrays like this:
total += array[i][j];
Where i won't change but j changes.
To traverse each column, go through the elements of your array of arrays like this:
total += array[i][j];
Where i changes but j won't change.
To traverse the up diagonal, go through the elements of your array of arrays like this:
total += array[i][j];
Where i starts at the last possible index of the array of arrays and j starts at the first index of the array of arrays.
Whenever I need to derive equations for certain behaviors, I just write a few of the answers out manually then look for patterns. First let's assume this is how we access items in the array:
column
0 1 2
--------
0 | 2 7 6
row 1 | 9 5 1
2 | 4 3 8
(Using array[column][row])
Now let's get the indices for the columns:
column 0 = {2, 9, 4} = array[0][0], array[0][1], array[0][2]
column 1 = {7, 5, 3} = array[1][0], array[1][1], array[1][2]
And here are the rows:
row 0 = {2, 7, 6} = array[0][0], array[1][0], array[2][0]
row 1 = {9, 5, 1} = array[0][1], array[1][1], array[2][1]
And here's the other diagonal:
3x3 array = {4, 5, 6} = array[0][2], array[1][1], array[2][0]
4x4 array = array[0][3], array[1][2], array[2][1], array[3][0]
Notice any patterns? For the diagonal, we start at array[0][array.length - 1] and end at array[array.length - 1][0]. This means our loop would be as follows:
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[i][array.length - 1 - i];
}
return total;
And to sum a column, it'd be:
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[column_index][i];
}
return total;
And for rows:
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[i][row_index];
}
return total;
EDIT: In response to downvotes and comments, I have modified the magic square code to work with row-major conventions. Oh wait, no I didn't since the code would be identical. Anyway, this is how you do it.
I have seen acrosss in a company interview test this question, but i am not clear about the question first. Could you people clarify my doubt ?
Question : Write a program to sort an integer array which contains Only 0's,1's and 2's. Counting of elements not allowed, you are expected to do it in O(n) time complexity.
Ex Array : {2, 0, 1, 2, 1, 2, 1, 0, 2, 0}
Output to a linked list.
Remember the beginning of the list.
Remember the position where the 1s start.
Remember the end of the list.
Run through the whole array.
If you encounter a 0, add it to the first position of the linked list.
If you encounter a 1, add it after the position of the 1.
If you encounter a 2, add it at the end of the list.
HTH
Raku
Instead of blasting you with yet another unintelligible pseudo-code, I’ll give you the name of the problem: this problem is known as the Dutch national flag problem (first proposed by Edsgar Dijkstra) and can be solved by a three-ways merge (see the PHP code in the first answer which solves this, albeit very inefficiently).
A more efficient in-place solution of the threeways merge is described in Bentley’s and McIlroy’s seminal paper Engineering a Sort Function. It uses four indices to delimit the ranges of the intermediate array, which has the unsorted values in the middle, the 1s at both edges, and the 0s and 2s in-between:
After having established this invariant, the = parts (i.e. the 1s) are swapped back into the middle.
It depends what you mean by "no counting allowed".
One simple way to do this would be to have a new empty array, then look for 0's, appending them to the new array. Repeat for 1's then 2's and it's sorted in O(n) time.
But this is more-or-less a radix sort. It's like we're counting the 0's then 1's then 2's, so I'm not sure if this fits your criteria.
Edit: we could do this with only O(1) extra memory by keeping a pointer for our insertion point (starting at the start of the array), and scanning through the array for 0's, swapping each 0 with the element where the pointer is, and incrementing the pointer. Then repeat for 1's, 2's and it's still O(n).
Java implementation:
import java.util.Arrays;
public class Sort
{
public static void main(String[] args)
{
int[] array = {2, 0, 1, 2, 1, 2, 1, 0, 2, 0};
sort(array);
System.out.println(Arrays.toString(array));
}
public static void sort(int[] array)
{
int pointer = 0;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < array.length; j++)
{
if(array[j] == i)
{
int temp = array[pointer];
array[pointer] = array[j];
array[j] = temp;
pointer++;
}
}
}
}
}
Gives output:
[0, 0, 0, 1, 1, 1, 2, 2, 2, 2]
Sorry, it's php, but it seems O(n) and could be easily written in java :)
$arr = array(2, 0, 1, 2, 1, 2, 1, 0, 2, 0);
$tmp = array(array(),array(),array());
foreach($arr as $i){
$tmp[$i][] = $i;
}
print_r(array_merge($tmp[0],$tmp[1],$tmp[2]));
In O(n), pseudo-code:
def sort (src):
# Create an empty array, and set pointer to its start.
def dest as array[sizeof src]
pto = 0
# For every possible value.
for val in 0, 1, 2:
# Check every position in the source.
for pfrom ranges from 0 to sizeof(src):
# And transfer if matching (includes update of dest pointer).
if src[pfrom] is val:
dest[pto] = val
pto = pto + 1
# Return the new array (or transfer it back to the source if desired).
return dest
This is basically iterating over the source list three times, adding the elements if they match the value desired on this pass. But it's still O(n).
The equivalent Java code would be:
class Test {
public static int [] mySort (int [] src) {
int [] dest = new int[src.length];
int pto = 0;
for (int val = 0; val < 3; val++)
for (int pfrom = 0; pfrom < src.length; pfrom++)
if (src[pfrom] == val)
dest[pto++] = val;
return dest;
}
public static void main(String args[]) {
int [] arr1 = {2, 0, 1, 2, 1, 2, 1, 0, 2, 0};
int [] arr2 = mySort (arr1);
for (int i = 0; i < arr2.length; i++)
System.out.println ("Array[" + i + "] = " + arr2[i]);
}
}
which outputs:
Array[0] = 0
Array[1] = 0
Array[2] = 0
Array[3] = 1
Array[4] = 1
Array[5] = 1
Array[6] = 2
Array[7] = 2
Array[8] = 2
Array[9] = 2
But seriously, if a potential employer gave me this question, I'd state straight out that I could answer the question if they wish, but that the correct answer is to just use Array.sort. Then if, and only if, there is a performance problem with that method and the specific data sets, you could investigate a faster way.
And that faster way would almost certainly involve counting, despite what the requirements were. You don't hamstring your developers with arbitrary limitations. Requirements should specify what is required, not how.
If you answered this question to me in this way, I'd hire you on the spot.
This answer doesn't count the elements.
Because there are so few values in the array, just count how many of each type there are and use that to repopulate your array. We also make use of the fact that the values are consecutive from 0 up - making it match the typical java int loop.
public static void main(String[] args) throws Exception
{
Integer[] array = { 2, 0, 1, 2, 1, 2, 1, 0, 2, 0 };
List<Integer>[] elements = new ArrayList[3]; // To store the different element types
// Initialize the array with new lists
for (int i = 0; i < elements.length; i++) elements[i] = new ArrayList<Integer>();
// Populate the lists
for (int i : array) elements[i].add(i);
for (int i = 0, start = 0; i < elements.length; start += elements[i++].size())
System.arraycopy(elements[i].toArray(), 0, array, start, elements[i].size());
System.out.println(Arrays.toString(array));
}
Output:
[0, 0, 0, 1, 1, 1, 2, 2, 2, 2]
Push and Pull have a constant complexity!
Push each element into a priority queue
Pull each element to indices 0...n
(:
You can do it in one pass, placing each encountered element to it's final position:
void sort012(int* array, int len) {
int* p0 = array;
int* p2 = array + len;
for (int* p = array; p <= p2; ) {
if (*p == 0) {
std::swap(*p, *p0);
p0++;
p++;
} else if (*p == 2) {
std::swap(*p, *p2);
p2--;
} else {
p++;
}
}
}
Because there are so few values in the array, just count how many of each type there are and use that to repopulate your array. We also make use of the fact that the values are consecutive from 0 up - making it match the typical java int loop.
The whole sorting algorithm requires only three lines of code:
public static void main(String[] args)
{
int[] array = { 2, 0, 1, 2, 1, 2, 1, 0, 2, 0 };
// Line 1: Define some space to hold the totals
int[] counts = new int[3]; // To store the (3) different totals
// Line 2: Get the total of each type
for (int i : array) counts[i]++;
// Line 3: Write the appropriate number of each type consecutively back into the array:
for (int i = 0, start = 0; i < counts.length; start += counts[i++]) Arrays.fill(array, start, start + counts[i], i);
System.out.println(Arrays.toString(array));
}
Output:
[0, 0, 0, 1, 1, 1, 2, 2, 2, 2]
At no time did we refer to array.length, no care how long the array was. It iterated through the array touching each element just once, making this algorithm O(n) as required.