I have an array that contains the total number of lines in 3 files. Example: [3,4,5]. I would like to produce a sequence of numbers that count that array down to zero in a methodical way giving me every combination of lines in the three files. This example uses 3 files/length-3 array, but the algorithm should be able to work an array with any arbitrary length.
For the example above, the solution would look like:
[3,4,5] (line 3 from file 1, line 4 from file 2, line 5 from file 3)
[3,4,4]
[3,4,3]
[3,4,2]
[3,4,1]
[3,4,0]
[3,3,5]
[3,3,4]
[3,3,3]
[3,3,2]
and so on...
My first attempt at producing an algorithm for this recursively decrements a position in the array, and when that position reaches zero - decrements the position before it. However I'm not able to keep the decrementing going for farther than the last two positions.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FilePositionGenerator {
public static void main(String[] args) {
int[] starterArray = {2, 2, 2};
int[] counters = starterArray.clone();
List<Integer> results = new ArrayList<Integer>();
FilePositionGenerator f = new FilePositionGenerator();
f.generateFilePositions(starterArray, counters, (starterArray.length - 1), results);
}//end main
void generateFilePositions(int[] originalArray, int[] modifiedArray, int counterPosition, List<Integer> results) {
if (modifiedArray[counterPosition] == 0 && counterPosition > 0) {
modifiedArray[counterPosition] = originalArray[counterPosition];
counterPosition = counterPosition - 1;
} else {
modifiedArray[counterPosition] = modifiedArray[counterPosition] - 1;
System.out.println(Arrays.toString(modifiedArray));
generateFilePositions(originalArray, modifiedArray, counterPosition, results);
}
}
}
I understand that to deal with a variable length array, the algorithm must be recursive, but I'm having trouble thinking it through. So I decided to try a different approach.
My second attempt at producing an algorithm uses a dual pointer method that keeps a pointer on the current countdown position[the rightmost position], and a pointer to the next non-rightmost position(pivotPointer) that will be decremented when the rightmost position reaches zero. Like so:
import java.util.Arrays;
class DualPointer {
public static void main(String[] args) {
int[] counters = {2, 2, 2}; // initialize the problem set
int[] original = {2, 2, 2}; // clone a copy to reset the problem array
int[] stopConditionArray = {0, 0, 0}; // initialize an object to show what the stopCondition should be
int pivotLocation = counters.length - 1; // pointer that starts at the right, and moves left
int counterLocation = counters.length - 1; // pointer that always points to the rightmost position
boolean stopCondition = false;
System.out.println(Arrays.toString(counters));
while (stopCondition == false) {
if (pivotLocation >= 0 && counterLocation >= 0 && counters[counterLocation] > 0) {
// decrement the rightmost position
counters[counterLocation] = counters[counterLocation] - 1;
System.out.println(Arrays.toString(counters));
} else if (pivotLocation >= 0 && counters[counterLocation] <= 0) {
// the rightmost position has reached zero, so check the pivotPointer
// and decrement if necessary, or move pointer to the left
if (counters[pivotLocation] == 0) {
counters[pivotLocation] = original[pivotLocation];
pivotLocation--;
}
counters[pivotLocation] = counters[pivotLocation] - 1;
counters[counterLocation] = original[counterLocation]; // reset the rightmost position
System.out.println(Arrays.toString(counters));
} else if (Arrays.equals(counters, stopConditionArray)) {
// check if we have reached the solution
stopCondition = true;
} else {
// emergency breakout of infinite loop
stopCondition = true;
}
}
}
}
Upon running, you can see 2 obvious problems:
[2, 2, 2]
[2, 2, 1]
[2, 2, 0]
[2, 1, 2]
[2, 1, 1]
[2, 1, 0]
[2, 0, 2]
[2, 0, 1]
[2, 0, 0]
[1, 2, 2]
[1, 2, 1]
[1, 2, 0]
[0, 2, 2]
[0, 2, 1]
[0, 2, 0]
Number one, the pivotPointer does not decrement properly when the pivotPointer and currentCountdown are more than one array cell apart. Secondly, there is an arrayIndexOutOfBounds at the line counters[pivotLocation] = counters[pivotLocation] - 1; that if fixed,
breaks the algorithm from running properly alltogether.
Any help would be appreciated.
I'll suggest a different approach.
The idea in recursion is to reduce the size of the problem in each recursive call, until you reach a trivial case, in which you don't have to make another recursive call.
When you first call the recursive method for an array of n elements, you can iterate in a loop over the range of values of the last index (n-1), make a recursive call to generate all the combinations for the array of the first n-1 elements, and combine the outputs.
Here's some partial Java/ partial pseudo code :
The first call :
List<int[]> output = generateCombinations(inputArray,inputArray.length);
The recursive method List<int[]> generateCombinations(int[] array, int length) :
List<int[]> output = new ArrayList<int[]>();
if length == 0
// the end of the recursion
for (int i = array[length]; i>=0; i--)
output.add (i)
else
// the recursive step
List<int[]> partialOutput = generateCombinations(array, length - 1)
for (int i = array[length]; i>=0; i--)
for (int[] arr : partialOutput)
output.add(arr + i)
return output
The recursive method returns a List<int[]>. This means that in "output.add (i)" you should create an int array with a single element and add it to the list, while in output.add(arr + i) you'll create an array of arr.length+1 elements, and copy to it the elements of arr followed by i.
The fun thing about recursion is that you can have it do exactly what you want it to. In this case, for each number at index i of your array of counts, we want to combine it with each number at index i + 1 until we reach the end of the array. The trick is not to return to index i once you've run through all the options for it.
JavaScript code:
var arr = [3,4,5];
var n = arr.length;
function f(cs,i){
// base case
if (i == n){
console.log(cs.join(','));
return;
}
// otherwise
while (cs[i] >= 0){
// copy counts
_cs = cs.slice();
// recurse
f(_cs,i + 1);
// change number at index i
cs[i]--;
}
}
f(arr,0);
Related
I'm working on the following task.
Given an array of n integers and two integer numbers m and k.
You can add any positive integer to any element of the array such that
the total value does not exceed k.
The task is to maximize the
multiples of m in the resultant array.
Consider the following example.
Input:
n = 5, m = 2, k = 2, arr[] = [1, 2, 3, 4, 5]
Let's add 1 to the element arr[0] and 1 to arr[2] then the final array would be:
[2, 2, 4, 4, 5]
Now there are four (4) elements which are multiples of m (2).
I am not getting correct output.
My code:
public class Main {
public static void main(String[] args) {
int n = 5;
int m = 4;
int k = 3;
int count = 0;
int[] arr = {17, 8, 9, 1, 4};
for (int i = 0; i < n; i++) {
for (int j = 0; j <= k; j++) {
// check initial
if (arr[i] % m == 0) {
break;
}
// add
arr[i] = arr[i] + j;
// check again
if (arr[i] % m == 0) {
count++;
break;
}
}
}
System.out.println("Final Array : " + Arrays.toString(arr));
System.out.println("Count : " + count);
}
}
This task boils down to a well-known Dynamic programming algorithm called Knapsack problem after a couple of simple manipulations with the given array.
This approach doesn't require sorting and would be advantages when k is much smaller n.
We can address the problem in the following steps:
Iterate over the given array and count all the numbers that are already divisible by m (this number is stored in the variable count in the code below).
While iterating, for every element of the array calculate the difference between m and remainder from the division of this element by m. Which would be equal to m - currentElement % m. If the difference is smaller or equal to k (it can cave this difference) it should be added to the list (differences in the code below) and also accumulated in a variable which is meant to store the total difference (totalDiff). All the elements which produce difference that exceeds k would be omitted.
If the total difference is less than or equal to k - we are done, the return value would be equal to the number of elements divisible by m plus the size of the list of differences.
Otherwise, we need to apply the logic of the Knapsack problem to the list of differences.
The idea behind the method getBestCount() (which is an implementation Knapsack problem) boils down to generating the "2D" array (a nested array of length equal to the size of the list of differences +1, in which every inner array having the length of k+1) and populating it with maximum values that could be achieved for various states of the Knapsack.
Each element of this array would represent the maximum total number of elements which can be adjusted to make them divisible by m for the various sizes of the Knapsack, i.e. number of items available from the list of differences, and different number of k (in the range from 0 to k inclusive).
The best way to understand how the algorithm works is to draw a table on a piece of paper and fill it with numbers manually (follow the comments in the code, some intermediate variables were introduced only for the purpose of making it easier to grasp, and also see the Wiki article linked above).
For instance, if the given array is [1, 8, 3, 9, 5], k=3 and m=3. We can see 2 elements divisible by m - 3 and 9. Numbers 1, 8, 5 would give the following list of differences [2, 1, 1]. Applying the logic of the Knapsack algorithm, we should get the following table:
[0, 0, 0, 0]
[0, 0, 1, 1]
[0, 1, 1, 2]
[0, 1, 2, 2]
We are interested in the value right most column of the last row, which is 2 plus 2 (number of elements divisible by 3) would give us 4.
Note: that code provided below can dial only with positive numbers. I don't want to shift the focus from the algorithm to such minor details. If OP or reader of the post are interested in making the code capable to work with negative number as well, I'm living the task of adjusting the code for them as an exercise. Hint: only a small change in the countMultiplesOfM() required for that purpose.
That how it might be implemented:
public static int countMultiplesOfM(int[] arr, int k, int m) {
List<Integer> differences = new ArrayList<>();
int count = 0;
long totalDiff = 0; // counter for the early kill - case when `k >= totalDiff`
for (int next : arr) {
if (next % m == 0)
count++; // number is already divisible by `m` we can increment the count and from that moment we are no longer interested in it
else if (m - next % m <= k) {
differences.add(m - next % m);
totalDiff += m - next % m;
}
}
if (totalDiff <= k) { // early kill - `k` is large enough to adjust all numbers in the `differences` list
return count + differences.size();
}
return count + getBestCount(differences, k); // fire the rest logic
}
// Knapsack Algorithm implementation
public static int getBestCount(List<Integer> differences, int knapsackSize) {
int[][] tab = new int[differences.size() + 1][knapsackSize + 1];
for (int numItemAvailable = 1; numItemAvailable < tab.length; numItemAvailable++) {
int next = differences.get(numItemAvailable - 1); // next available item which we're trying to place to knapsack to Maximize the current total
for (int size = 1; size < tab[numItemAvailable].length; size++) {
int prevColMax = tab[numItemAvailable][size - 1]; // maximum result for the current size - 1 in the current row of the table
int prevRowMax = tab[numItemAvailable - 1][size]; // previous maximum result for the current knapsack's size
if (next <= size) { // if it's possible to fit the next item in the knapsack
int prevRowMaxWithRoomForNewItem = tab[numItemAvailable - 1][size - next] + 1; // maximum result from the previous row for the size = `current size - next` (i.e. the closest knapsack size which guarantees that there would be a space for the new item)
tab[numItemAvailable][size] = Math.max(prevColMax, prevRowMaxWithRoomForNewItem);
} else {
tab[numItemAvailable][size] = Math.max(prevRowMax, prevColMax); // either a value in the previous row or a value in the previous column of the current row
}
}
}
return tab[differences.size()][knapsackSize];
}
main()
public static void main(String[] args) {
System.out.println(countMultiplesOfM(new int[]{17, 8, 9, 1, 4}, 3, 4));
System.out.println(countMultiplesOfM(new int[]{1, 2, 3, 4, 5}, 2, 2));
System.out.println(countMultiplesOfM(new int[]{1, 8, 3, 9, 5}, 3, 3));
}
Output:
3 // input array [17, 8, 9, 1, 4], m = 4, k = 3
4 // input array [1, 2, 3, 4, 5], m = 2, k = 2
4 // input array [1, 8, 3, 9, 5], m = 3, k = 3
A link to Online Demo
You must change 2 line in your code :
if(arr[i]%m==0)
{
count++; // add this line
break;
}
// add
arr[i]=arr[i]+1; // change j to 1
// check again
if(arr[i]%m==0)
{
count++;
break;
}
The first is because the number itself is divisible.
and The second is because you add a number to it each time.That is wrong.
for example chenge your arr to :
int[] arr ={17,8,10,2,4};
your output is :
Final Array : [20, 8, 16, 8, 4]
and That is wrong because 16-10=6 and is bigger than k=3.
I believe the problem is that you aren't processing the values in ascending order of the amount by which to adjust.
To solve this I started by using a stream to preprocess the array. This could be done using other methods.
map the values to the amount to make each one, when added, divisible by m.
filter out those that equal to m' (already divisible by m`)
sort in ascending order.
Once that is done. Intialize max to the difference between the original array length and the processed length. This is the number already divisible by m.
As the list is iterated
check to see if k > amount needed. If so, subtract from k and increment max
otherwise break out of the loop (because of the sort, no value remaining can be less than k)
public static int maxDivisors(int m, int k, int[] arr) {
int[] need = Arrays.stream(arr).map(v -> m - v % m)
.filter(v -> v != m).sorted().toArray();
int max = arr.length - need.length;
for (int val : need) {
if (k >= val) {
k -= val;
max++;
} else {
break;
}
}
return max;
}
int m = 4;
int k = 3;
int[] arr ={17,8,9,1,4};
int count = maxDivisors(m, k, arr);
System.out.println(count);
prints
3
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.
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.
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.
i have array values as like
String[] value = {"1","2","3", "4","5","6","7","8","9","10"};
suppose if i pass value "5" to tat array, it should be ordered as like
{"5","6","7","8","9","10",1","2","3","4"};...
how to do?plz anyone help?
thank u
What you need is called rotation. You can use Collections.rotate() method. Convert the array to a list and pass it to the method. This will rotate the array in place since the list is backed by the array:
String[] value = {"1","2","3", "4","5","6","7","8","9","10"};
Collections.rotate(Arrays.asList(value), 5);
The above code will rotate the array by a distance of 5. The resulting value array:
[6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
Your question has two interpretations:
Rotate 5 steps, or
rotate the array so that 5 is the first element (regardless of where it is in the array).
Here is a solution for both alternatives:
import java.util.Arrays;
public class Test {
public static String[] rotateArray(String[] arr, int n) {
String[] rotated = new String[arr.length];
System.arraycopy(arr, n-1, rotated, 0, arr.length-n+1);
System.arraycopy(arr, 0, rotated, arr.length-n+1, n-1);
return rotated;
}
public static String[] rotateArrayTo(String[] arr, String head) {
for (int i = 0; i < arr.length; i++)
if (arr[i].equals(head))
return rotateArray(arr, i + 1);
throw new IllegalArgumentException("Could not find " + head);
}
public static void main(String[] args) {
String[] value = {"1","2","3","4","5","6","7","8","9","10"};
// Rotate so that it starts at 5:th element
value = rotateArray(value, 5);
System.out.println(Arrays.toString(value));
// Rotate so that it starts with element "7"
value = rotateArrayTo(value, "7");
System.out.println(Arrays.toString(value));
}
}
Output:
[5, 6, 7, 8, 9, 10, 1, 2, 3, 4]
[7, 8, 9, 10, 1, 2, 3, 4, 5, 6]
(ideone.com link)
first find the index of the entered value from the array..
and then in a loop move from the index to the final position.. and store these values in a new array.
after that, in the same result array, store the values from index 0 to the index of the entered value - 1.
You really don't need to store the values in a different array. Just find the index [say idx] of the value passed. And then start a loop from the start of the array and swap the values starting from idx.
For example -
idx = [some-value]
while [idx < arr.length]
temp = arr[i]
arr[i] = arr[idx]
arr[idx] = t
idx += 1
i += 1
Update:
I stand corrected by #aioobe. I simply worked out something for the 5th index - my bad. Here's something that works, if in case, you want to stay away from library functions -
private void slideLeft(String[] arr)
{
String t = arr[arr.length - 1];
String temp = null;
int next = -1;
for (int i = arr.length - 1; i >= 0; i--)
{
next = ( i == 0 ) ? arr.length - 1 : i - 1;
temp = arr[next];
arr[next] = t;
t = temp;
}
}
you'll need to call this method the number of times you need to shift the array members.
note: O(n^2) alert. not suitable for large shifts/arrays.