How to sort a disjoint sublist? - algorithm

Let's say I have the following list: [2, 1, 4, 6, 3, 7]. I also have some method that sorts any list. However, I want to perform a sort across only elements at indices 1, 2, & 4, i.e. the sublist [1, 4, 3]. Sorting across this sublist produces [1, 3, 4]. How can get the original list such that I only sort across indices 1, 2, and 4, i.e., [2, 1, 3, 6, 4, 7]?

The easiest way is probably to use an extra level of indirection. For example, create a list (here meaning just some linear collection, not necessarily a linked list) of the indexes of the three elements you want to sort, and code to do comparison/swapping through that layer of indirection.

Thanks to the suggestion by Jerry Coffin, here's the solution in Java for those who are interested:
import java.util.List;
import java.util.AbstractList;
import java.util.Arrays;
public class ExtendedSubList<E> extends AbstractList<E>
{
protected final List<E> parent;
protected final int[] indices;
public static <E> List<E> subList(final List<E> parent, int ... indices)
{
if (parent == null)
throw new IllegalArgumentException("parent == null");
if (indices == null)
throw new IllegalArgumentException("indices == null");
for (int i = 0; i < indices.length; i++)
if (!(0 <= indices[i] && indices[i] < parent.size()))
throw new IllegalArgumentException(String.format("index %d (at position %d) is not in bounds", indices[i], i));
Arrays.sort(indices);
return new ExtendedSubList(parent, indices);
}
protected ExtendedSubList(List<E> parent, int[] indices)
{
this.parent = parent;
this.indices = indices;
}
public E get(int index)
{
return parent.get(indices[index]);
}
public int size()
{
return indices.length;
}
public E set(int index, E element)
{
return parent.set(indices[index], element);
}
}
Usage example:
List<Integer> list = Arrays.asList(2, 1, 4, 6, 3, 7);
Collections.sort(ExtendedSubList.subList(list), 1, 2, 4);
The resulting list would produce: [2, 1, 3, 6, 4, 7].

The following Python code does the job. It may differ from Jerry Coffins accepted answer as rather than sorting through indirection it extracts the values, sorts, then inserts them back.
data = [7, 6, 5, 4, 3, 2, 1, 0]
indices = sorted([1,2,4])
values = [data[i] for i in indices] # [6, 5, 3]
values.sort() # [3, 5, 6]
for index, value in zip(indices, values):
data[index] = value
print (data) # [7, 3, 5, 4, 6, 2, 1, 0]
The original indices should be
sorted for things to work.
The corresponding values are
extracted.
The values are sorted.
The for loop puts the sorted values
back into the original array.

Related

Length of maximum continuous subarray with 2 unique numbers

I have an array of numbers and I want to figure out the maximum length of a continuous subarray of 2 unique numbers repeating.
For example, [2, 3, 4, 3, 2, 2, 4] would return 3 since [3, 2, 2] is of length 3.
[2, 4, 2, 5, 1, 5, 4, 2] would return 3.
[7, 8, 7, 8, 7] would return 5.
Edit: I have considered an O(n^2) solution where I start at each value in the array and iterate until I see a third unique value.
for item in array:
iterate until third unique element
if length of this iteration is greater than existing max, update the max length
return maxlength
I do not, however, think this is an efficient solution.
It can be done O(n). The code is in python3. o and t are one and two respectively. m is the max and c is the current count variable.
a = [7, 8, 7, 8, 7]
m = -1
o = a[0]
t = a[1]
# in the beginning one and two are the first 2 numbers
c = 0
index = 0
for i in a:
if i == o or i == t:
# if current element is either one or two current count is increased
c += 1
else:
# if current element is neither one nor two then they are updated accordingly and max is updated
o = a[index - 1]
t = a[index]
m = max(m, c)
c = 2
index += 1
m = max(m, c)
print(m)
We can use two pointer technique to solve this problem in O(n) run time complexity. These two pointer for example startPtr and endPtr will represent the range in the array. We will maintain this range [startPtr, endPtr] in such way that it contains no more than 2 unique number. We can do this by keeping track of position of the 2 unique number. My implement in C++ is given below:
int main()
{
int array[] = {1,2,3,3,2,3,2,3,2,2,2,1,3,4};
int startPtr = 0;
int endPtr = 0;
// denotes the size of the array
int size= sizeof(array)/sizeof(array[0]);
// contain last position of unique number 1 in the range [startPtr, endPtr]
int uniqueNumPos1 = -1; // -1 value represents it is not set yet
// contain last position of unique number 2 in the range [startPtr, endPtr]
int uniqueNumPos2 = -1; // -1 value represents it is not set yet
// contains length of maximum continuous subarray with 2 unique numbers
int ans = 0;
while(endPtr < size) {
if(uniqueNumPos1 == -1 || array[endPtr] == array[uniqueNumPos1]) {
uniqueNumPos1 = endPtr;
}
else {
if(uniqueNumPos2 == -1 || array[endPtr] == array[uniqueNumPos2]) {
uniqueNumPos2 = endPtr;
}
else {
// for this new third unique number update startPtr with min(uniqueNumPos1, uniqueNumPos2) + 1
// to ensure [startPtr, endPtr] does not contain more that two unique
startPtr = min(uniqueNumPos1, uniqueNumPos2) + 1;
// update uniqueNumPos1 and uniqueNumPos2
uniqueNumPos1 = endPtr -1;
uniqueNumPos2 = endPtr;
}
}
// this conditon is to ensure the range contain exactly two unique number
// if you are looking for the range containing less than or equal to two unique number, then you can omit this condition
if (uniqueNumPos1 != -1 && uniqueNumPos2 !=-1) {
ans = max( ans, endPtr - startPtr + 1);
}
endPtr++;
}
printf("%d\n", ans);
}
Thanks #MBo for pointing out the mistakes.
import java.util.Arrays;
import static java.lang.System.out;
class TestCase{
int[] test;
int answer;
TestCase(int[] test,int answer){
this.test = test;
this.answer = answer;
}
}
public class Solution {
public static void main(String[] args) {
TestCase[] tests = {
new TestCase(new int[]{2, 3, 4, 3, 2, 2, 4},3),
new TestCase(new int[]{2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 4},7),
new TestCase(new int[]{1,2,3,3,4,2,3,2,3,2,2,2,1,3,4},7),
new TestCase(new int[]{2, 7, 8, 7, 8, 7},5),
new TestCase(new int[]{-1,2,2,2,2,2,2,2,2,2,2,-1,-1,4},13),
new TestCase(new int[]{1,2,3,4,5,6,7,7},3),
new TestCase(new int[]{0,0,0,0,0},0),
new TestCase(new int[]{0,0,0,2,2,2,1,1,1,1},7),
new TestCase(new int[]{},0)
};
for(int i=0;i<tests.length;++i){
int ans = maxContiguousArrayWith2UniqueElements(tests[i].test);
out.println(Arrays.toString(tests[i].test));
out.println("Expected: " + tests[i].answer);
out.println("Returned: " + ans);
out.println("Result: " + (tests[i].answer == ans ? "ok" : "not ok"));
out.println();
}
}
private static int maxContiguousArrayWith2UniqueElements(int[] A){
if(A == null || A.length <= 1) return 0;
int max_subarray = 0;
int first_number = A[0],second_number = A[0];
int start_index = 0,same_element_run_length = 1;
for(int i=1;i<A.length;++i){
if(A[i] != A[i-1]){
if(first_number == second_number){
second_number = A[i];
}else{
if(A[i] != first_number && A[i] != second_number){
max_subarray = Math.max(max_subarray,i - start_index);
start_index = i - same_element_run_length;
first_number = A[i-1];
second_number = A[i];
}
}
same_element_run_length = 1;
}else{
same_element_run_length++;
}
}
return first_number == second_number ? max_subarray : Math.max(max_subarray,A.length - start_index);
}
}
OUTPUT:
[2, 3, 4, 3, 2, 2, 4]
Expected: 3
Returned: 3
Result: ok
[2, 3, 3, 3, 3, 4, 3, 3, 2, 2, 4]
Expected: 7
Returned: 7
Result: ok
[1, 2, 3, 3, 4, 2, 3, 2, 3, 2, 2, 2, 1, 3, 4]
Expected: 7
Returned: 7
Result: ok
[2, 7, 8, 7, 8, 7]
Expected: 5
Returned: 5
Result: ok
[-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, 4]
Expected: 13
Returned: 13
Result: ok
[1, 2, 3, 4, 5, 6, 7, 7]
Expected: 3
Returned: 3
Result: ok
[0, 0, 0, 0, 0]
Expected: 0
Returned: 0
Result: ok
[0, 0, 0, 2, 2, 2, 1, 1, 1, 1]
Expected: 7
Returned: 7
Result: ok
[]
Expected: 0
Returned: 0
Result: ok
Algorithm:
So, we maintain 2 variables first_number and second_number which will hold those 2 unique numbers.
As you know, there could be many possible subarrays we have to consider to get the max subarray length which has 2 unique elements. Hence, we need a pointer variable which will point to start of a subarray. In this, that pointer is start_index.
Any subarray breaks when we find a third number which is not equal to first_number or second_number. So, now, we calculate the previous subarray length(which had those 2 unique elements) by doing i - start_index.
Tricky part of this question is how to get the start_index of the next subarray.
If you closely observe, second_number of previous subarray becomes first_number of current subarray and third number we encountered just now becomes second_number of this current subarray.
So, one way to calculate when this first_number started is to run a while loop backwards to get that start_index. But that would make the algorithm O(n^2) if there are many subarrays to consider(which it will be).
Hence, we maintain a variable called same_element_run_length which just keeps track of the length or frequency of how many times the number got repeated and gets updated whenever it breaks. So, start_index for the next subarray after we encounter the third number becomes start_index = i - same_element_run_length.
Rest of the computation done is self-explanatory.
Time Complexity: O(n), Space Complexity : O(1).

Getting ALL permutations of ALL sublists of a list of integers

I've been having trouble with this problem. Basically, I have a list of integers, such as
list = [1, 2, 3]
I want to get all possible permutations of every subset. I know similar questions exist online, but I couldn't find one that does every permutation as well as every subset. In other words, I want:
function(list) =
[], [1], [2], [3],
[1, 2], [2, 1], [1, 3], [3,1], [2, 3], [3,2],
[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]
I understand the output will get extremely large even for a small input list size. Unfortunately, I just cannot figure out how to do such a problem.
Thank you!
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
private static boolean[] used;
private static int[] a;
private static void f(int curCount,int subsetSize,ArrayDeque<Integer> perm){
// System.out.println("in rec "+curCount+" "+subsetSize);
if(curCount < subsetSize){
for(int i=0;i<a.length;i++) {
if (!used[i]) { // try to add i-th elem of array as a next element of permutation if it's not busy
perm.add(a[i]);
used[i] = true; //mark i-th element as used for future recursion calls
f(curCount + 1, subsetSize,perm); // curCount+1 because we added elem to perm. subsetSize is const and it's needed just for recursion exit condition
used[i] = false; // "free" i-th element
perm.removeLast();
}
}
}
else{ //some permutation of array subset with size=subsetSize generated
for(Integer xx:perm) System.out.print(xx+" ");
System.out.println();
}
}
public static void main(String[] args){
a = new int[]{1,2,3};
used = new boolean[a.length];
Arrays.fill(used, false);
// second param is a subset size (all sizes from 1 to n)
// first param is number of "collected" numbers, when collected numbers==required subset size (firstparam==second param) exit from recursion (from some particular call-chain)
// third param is data structure for constructing permutation
for(int i=1;i<=a.length;i++)f(0,i,new ArrayDeque<Integer>());
} //end of main
} //end of class
output
1 2 3 1 2 1 3 2 1 2 3 3 1
3 2 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2
3 2 1
So what you are looking for is all the possible permutations of the Power Set.
This seems to go into some depth about strategies for doing this.
If your list in N elements long, you want to get all the combinations of N taken by M, where M is between 1 and N. For each of the combination you want to get all the permutations. You can probably figure out algorithms for combinations and permutations via google.
I ended up using a combination of these two functions. Not sure if it works as intended, but so far it has been working properly.
// Generates all permutations of a set. Thus, given an input like [1, 2, 3] it changes the null
// final_list input to be [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
static void heappermute(List<List<Integer>> waypoints, int n, List<List<List<Integer>>> final_list) {
int i;
if (n == 1) {
final_list.add(waypoints);
}
else {
for (i = 0; i < n; i++) {
heappermute(waypoints, n-1, final_list);
if (n % 2 == 1) {
swap(waypoints.get(0), waypoints.get(n-1));
}
else {
swap(waypoints.get(i), waypoints.get(n-1));
}
}
}
}
static void swap (List<Integer> x, List<Integer> y)
{
List<Integer> temp = new ArrayList<>();
temp = x;
x = y;
y = temp;
}
// Generates all subsets of a given set. Thus, given a list of waypoints, it will return a list of
// waypoint lists, each of which is a subset of the original list of waypoints.
// Ex: Input originalSet = {1, 2, 3}
// Output: = {}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}
// Code modified from http://stackoverflow.com/questions/4640034/calculating-all-of-the-subsets-of-a-set-of-numbers
public static List<List<List<Integer>>> powerSet(List<List<Integer>> originalSet) {
List<List<List<Integer>>> sets = new ArrayList<>();
if (originalSet.isEmpty()) {
sets.add(new ArrayList<List<Integer>>());
return sets;
}
List<List<Integer>> list = new ArrayList<List<Integer>>(originalSet);
List<Integer> head = list.get(0);
List<List<Integer>> rest = new ArrayList<List<Integer>>(list.subList(1, list.size()));
for (List<List<Integer>> set : powerSet(rest)) {
List<List<Integer>> newSet = new ArrayList<List<Integer>>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}

How to find duplicate element in array and return duplicate index

I need to find duplicate latitude in an array and nudge it a bit to avoid marker display problem.
I searched and find a way to do it in ruby:
1.find duplicate element in ruby
(I consider sort array element and check adjacent element)
2.use array.indexof() to get its index(may have 3 or more duplicate element)
This works sure but I feel its not the best way. Is there a way to find duplicate and index of duplicate in one go?
Thanks in advance
EDIT:
I've find a way,check duplicate and change on spot.
But the problem is this function change all duplicate value to another duplicated value.
I think its because the main array is not updated during check and change procedure, attached is my code,anyway to improve it?
#ln=0
for #ln in 0..#checkLocation.length-1 do
if (!(#checkLocation.index(#existlat)==nil) && (#existlat!=nil))
#checkLocation[#ln]=#checkLocation[#ln]+0.00001
end
#existlat=#checkLocation[#ln]
end
a = [:a, :b, :c, :b, :d, :a, :e]
a.each_index.group_by{|i| a[i]}.values.select{|a| a.length > 1}.flatten
# => [0, 5, 1, 3]
Finding dupes is not very difficult if performance is not a real issue for you.
The most natural way would be to compare each element with all the other elements:
for (int i = 0; i < arraySize-1; ++i) {
for (int j = i+1; j < arraySize; ++j) {
if(array[i] == array[j]) changeDupe(array[j]);
}
}
The code above will allow you to change all the dupes.
Example in execution, changin dupes to 0:
Input: {1, 2, 3, 2, 1, 4, 5, 6, 8, 2}
Output: {1, 2, 3, 0, 0, 4, 5, 6, 8, 0}
Another way to achieve this is to use a second array. If you are using integer values, you can make it like this:
int input[10] = {1, 2, 3, 2, 1, 4, 5, 6, 8, 2};
bool output[10] = {false, false, false, false, false, false, false, false, false, false};
for (int i = 0; i < arraySize; ++i) {
if (output[input[i]] == false) changeDupe(input[i]));
else output[input[i]] = true;
}
However, if one of your elements is bigger than the size of your array you will have a boundary problem. Suppose you have the value 100, then you would be trying to access the 100th element of the boolean array.
If you want to use the second algorithm but you are not working with an integer array, you could use a map to map each value on your array to an int, and then use the map value to set the booleans.
A pseudocode would look like this:
Map<yourData, int> map;
map<someValue, 1>;
map[someValue] = 1; //work based on this return value;
Yeeeet another way is to sort the array before iterating over it, and stop once you hit a different number. This would diminish the number of times you iterate over the array, but you would be adding the sorting algorithm complexity (probably O(n log(n))).
The code would look something like this:
int i = 0;
while (i < arraySize-1) {
if(array[i] == array[i+1])
array[i] = 0;
i++;
}
Input: {1, 1, 2, 3, 3, 4, 5, 6, 7, 8};
Output: {0, 1, 2, 0, 3, 4, 5, 6, 7, 8}
Complexity:
for the first algorithm, you would have N*(N-1) which I would say is O(n²).
for the second is O(n), but restrictions apply.
for the third, it would be the sort + O(n) for the loop.

How to sort an array using minimum number of writes?

My friend was asked a question in his interview:
The interviewer gave him an array of unsorted numbers and asked him to sort. The restriction is that the number of writes should be minimized while there is no limitation on the number of reads.
Selection sort is not the right algorithm here. Selection sort will swap values, making up to two writes per selection, giving a maximum of 2n writes per sort.
An algorithm that's twice as good as selection sort is "cycle" sort, which does not swap. Cycle sort will give a maximum of n writes per sort. The number of writes is absolutely minimized. It will only write a number once to its final destination, and only then if it's not already there.
It is based on the idea that all permutations are products of cycles and you can simply cycle through each cycle and write each element to its proper place once.
import java.util.Random;
import java.util.Collections;
import java.util.Arrays;
public class CycleSort {
public static final <T extends Comparable<T>> int cycleSort(final T[] array) {
int writes = 0;
// Loop through the array to find cycles to rotate.
for (int cycleStart = 0; cycleStart < array.length - 1; cycleStart++) {
T item = array[cycleStart];
// Find where to put the item.
int pos = cycleStart;
for (int i = cycleStart + 1; i < array.length; i++)
if (array[i].compareTo(item) < 0) pos++;
// If the item is already there, this is not a cycle.
if (pos == cycleStart) continue;
// Otherwise, put the item there or right after any duplicates.
while (item.equals(array[pos])) pos++;
{
final T temp = array[pos];
array[pos] = item;
item = temp;
}
writes++;
// Rotate the rest of the cycle.
while (pos != cycleStart) {
// Find where to put the item.
pos = cycleStart;
for (int i = cycleStart + 1; i < array.length; i++)
if (array[i].compareTo(item) < 0) pos++;
// Put the item there or right after any duplicates.
while (item.equals(array[pos])) pos++;
{
final T temp = array[pos];
array[pos] = item;
item = temp;
}
writes++;
}
}
return writes;
}
public static final void main(String[] args) {
final Random rand = new Random();
final Integer[] array = new Integer[8];
for (int i = 0; i < array.length; i++) { array[i] = rand.nextInt(8); }
for (int iteration = 0; iteration < 10; iteration++) {
System.out.printf("array: %s ", Arrays.toString(array));
final int writes = cycleSort(array);
System.out.printf("sorted: %s writes: %d\n", Arrays.toString(array), writes);
Collections.shuffle(Arrays.asList(array));
}
}
}
A few example runs :
array: [3, 2, 6, 1, 3, 1, 4, 4] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [1, 3, 4, 1, 3, 2, 4, 6] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 4
array: [3, 3, 1, 1, 4, 4, 2, 6] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [1, 1, 3, 2, 4, 3, 6, 4] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [3, 2, 3, 4, 6, 4, 1, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [6, 2, 4, 3, 1, 3, 4, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 6
array: [6, 3, 2, 4, 3, 1, 4, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 5
array: [4, 2, 6, 1, 1, 4, 3, 3] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [4, 3, 3, 1, 2, 4, 6, 1] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [1, 6, 4, 2, 4, 1, 3, 3] sorted: [1, 1, 2, 3, 3, 4, 4, 6] writes: 7
array: [5, 1, 2, 3, 4, 3, 7, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 5
array: [5, 1, 7, 3, 2, 3, 4, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 6
array: [4, 0, 3, 1, 5, 2, 7, 3] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 8
array: [4, 0, 7, 3, 5, 1, 3, 2] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [3, 4, 2, 7, 5, 3, 1, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [0, 5, 3, 2, 3, 7, 1, 4] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 6
array: [1, 4, 3, 7, 2, 3, 5, 0] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [1, 5, 0, 7, 3, 3, 4, 2] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
array: [0, 5, 7, 3, 3, 4, 2, 1] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 4
array: [7, 3, 1, 0, 3, 5, 4, 2] sorted: [0, 1, 2, 3, 3, 4, 5, 7] writes: 7
If the array is shorter (ie less than about 100 elements) a Selection sort is often the best choice if you also want to reduce the number of writes.
From wikipedia:
Another key difference is that
selection sort always performs Θ(n)
swaps, while insertion sort performs
Θ(n2) swaps in the average and worst
cases. Because swaps require writing
to the array, selection sort is
preferable if writing to memory is
significantly more expensive than
reading. This is generally the case if
the items are huge but the keys are
small. Another example where writing
times are crucial is an array stored
in EEPROM or Flash. There is no other
algorithm with less data movement.
For larger arrays/lists Quicksort and friends will provide better performance, but may still likely need more writes than a selection sort.
If you're interested this is a fantastic sort visualization site that allows you to watch specific sort algorithms do their job and also "race" different sort algorithms against each other.
You can use a very naive algorithm that satisfies what you need.
The algorithm should look like this:
i = 0
do
search for the minimum in range [i..n)
swap a[i] with a[minPos]
i = i + 1
repeat until i = n.
The search for the minimum can cost you almost nothing, the swap costs you 3 writes, the i++ costs you 1..
This is named selection sort as stated by ash. (Sorry, I didn't knew it was selection sort :( )
One option for large arrays is as follows (assuming n elements):
Initialize an array with n elements numbered 0..n-1
Sort the array using any sorting algorithm. As the comparison function, compare the elements in the input set with the corresponding numbers (eg, to compare 2 and 4, compare the 2nd and 4th elements in the input set). This turns the array from step 1 into a permutation that represents the sorted order of the input set.
Iterate through the elements in the permutation, writing out the blocks in the order specified by the array. This requires exactly n writes, the minimum.
To sort in-place, in step 3 you should instead identify the cycles in the permutation, and 'rotate' them as necessary to result in sorted order.
The ordering I meant in O(n) is like the selection sort(the previous post) useful when you have a small range of keys (or you are ordering numbers between 2 ranges)
If you have a number array where numbers will be between -10 and 100, then you can create an array of 110 and be sure that all numbers will fit in there, if you consider repeated numbers the idea is the same, but you will have lists instead of numbers in the sorted array
the pseudo-idea is like this
N: max value of your array
tosort //array to be sorted
sorted = int[N]
for i = 0 to length(tosort)
do
sorted[tosort[i]]++;
end
finalarray = int[length(tosort)]
k = 0
for i = 0 to N
do
if ( sorted[i] > 0 )
finalarray[k] = i
k++;
endif
end
finalarray will have the final sorted array and you will have o(N) write operations, where N is the range of the array. Once again, this is useful when using keys inside a specific range, but perhaps its your case.
Best regards and good luck!

Generating the partitions of a number

I needed an algorithm to generate all possible partitions of a positive number, and I came up with one (posted as an answer), but it's exponential time.
The algorithm should return all the possible ways a number can be expressed as the sum of positive numbers less than or equal to itself. So for example for the number 5, the result would be:
5
4+1
3+2
3+1+1
2+2+1
2+1+1+1
1+1+1+1+1
So my question is: is there a more efficient algorithm for this?
EDIT: Question was titled "Sum decomposition of a number", since I didn't really know what this was called. ShreevatsaR pointed out that they were called "partitions," so I edited the question title accordingly.
It's called Partitions. [Also see Wikipedia: Partition (number theory).]
The number of partitions p(n) grows exponentially, so anything you do to generate all partitions will necessarily have to take exponential time.
That said, you can do better than what your code does. See this, or its updated version in Python Algorithms and Data Structures by David Eppstein.
Here's my solution (exponential time) in Python:
q = { 1: [[1]] }
def decompose(n):
try:
return q[n]
except:
pass
result = [[n]]
for i in range(1, n):
a = n-i
R = decompose(i)
for r in R:
if r[0] <= a:
result.append([a] + r)
q[n] = result
return result
>>> decompose(5)
[[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]
When you ask to more efficient algorithm, I don't know which to compare. But here is one algorithm written in straight forward way (Erlang):
-module(partitions).
-export([partitions/1]).
partitions(N) -> partitions(N, N).
partitions(N, Max) when N > 0 ->
[[X | P]
|| X <- lists:seq(min(N, Max), 1, -1),
P <- partitions(N - X, X)];
partitions(0, _) -> [[]];
partitions(_, _) -> [].
It is exponential in time (same as Can Berk Güder's solution in Python) and linear in stack space. But using same trick, memoization, you can achieve big improvement by save some memory and less exponent. (It's ten times faster for N=50)
mp(N) ->
lists:foreach(fun (X) -> put(X, undefined) end,
lists:seq(1, N)), % clean up process dictionary for sure
mp(N, N).
mp(N, Max) when N > 0 ->
case get(N) of
undefined -> R = mp(N, 1, Max, []), put(N, R), R;
[[Max | _] | _] = L -> L;
[[X | _] | _] = L ->
R = mp(N, X + 1, Max, L), put(N, R), R
end;
mp(0, _) -> [[]];
mp(_, _) -> [].
mp(_, X, Max, R) when X > Max -> R;
mp(N, X, Max, R) ->
mp(N, X + 1, Max, prepend(X, mp(N - X, X), R)).
prepend(_, [], R) -> R;
prepend(X, [H | T], R) -> prepend(X, T, [[X | H] | R]).
Anyway you should benchmark for your language and purposes.
Here's a much more long-winded way of doing it (this is what I did before I knew the term "partition", which enabled me to do a google search):
def magic_chunker (remainder, chunkSet, prevChunkSet, chunkSets):
if remainder > 0:
if prevChunkSet and (len(prevChunkSet) > len(chunkSet)): # counting down from previous
# make a chunk that is one less than relevant one in the prevChunkSet
position = len(chunkSet)
chunk = prevChunkSet[position] - 1
prevChunkSet = [] # clear prevChunkSet, no longer need to reference it
else: # begins a new countdown;
if chunkSet and (remainder > chunkSet[-1]): # no need to do iterations any greater than last chunk in this set
chunk = chunkSet[-1]
else: # i.e. remainder is less than or equal to last chunk in this set
chunk = remainder #else use the whole remainder for this chunk
chunkSet.append(chunk)
remainder -= chunk
magic_chunker(remainder, chunkSet, prevChunkSet, chunkSets)
else: #i.e. remainder==0
chunkSets.append(list(chunkSet)) #save completed partition
prevChunkSet = list(chunkSet)
if chunkSet[-1] > 1: # if the finalchunk was > 1, do further recursion
remainder = chunkSet.pop() #remove last member, and use it as remainder
magic_chunker(remainder, chunkSet, prevChunkSet, chunkSets)
else: # last chunk is 1
if chunkSet[0]==1: #the partition started with 1, we know we're finished
return chunkSets
else: #i.e. still more chunking to go
# clear back to last chunk greater than 1
while chunkSet[-1]==1:
remainder += chunkSet.pop()
remainder += chunkSet.pop()
magic_chunker(remainder, chunkSet, prevChunkSet, chunkSets)
partitions = []
magic_chunker(10, [], [], partitions)
print partitions
>> [[10], [9, 1], [8, 2], [8, 1, 1], [7, 3], [7, 2, 1], [7, 1, 1, 1], [6, 4], [6, 3, 1], [6, 2, 2], [6, 2, 1, 1], [6, 1, 1, 1, 1], [5, 5], [5, 4, 1], [5, 3, 2], [5, 3, 1, 1], [5, 2, 2, 1], [5, 2, 1, 1, 1], [5, 1, 1, 1, 1, 1], [4, 4, 2], [4, 4, 1, 1], [4, 3, 3], [4, 3, 2, 1], [4, 3, 1, 1, 1], [4, 2, 2, 2], [4, 2, 2, 1, 1], [4, 2, 1, 1, 1, 1], [4, 1, 1, 1, 1, 1, 1], [3, 3, 3, 1], [3, 3, 2, 2], [3, 3, 2, 1, 1], [3, 3, 1, 1, 1, 1], [3, 2, 2, 2, 1], [3, 2, 2, 1, 1, 1], [3, 2, 1, 1, 1, 1, 1], [3, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [2, 2, 2, 2, 1, 1], [2, 2, 2, 1, 1, 1, 1], [2, 2, 1, 1, 1, 1, 1, 1], [2, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
Java implementation. Could benefit from memoization.
public class Partition {
/**
* partition returns a list of int[] that represent all distinct partitions of n.
*/
public static List<int[]> partition(int n) {
List<Integer> partial = new ArrayList<Integer>();
List<int[]> partitions = new ArrayList<int[]>();
partition(n, partial, partitions);
return partitions;
}
/**
* If n=0, it copies the partial solution into the list of complete solutions.
* Else, for all values i less than or equal to n, put i in the partial solution and partition the remainder n-i.
*/
private static void partition(int n, List<Integer> partial, List<int[]> partitions) {
//System.out.println("partition " + n + ", partial solution: " + partial);
if (n == 0) {
// Complete solution is held in 'partial' --> add it to list of solutions
partitions.add(toArray(partial));
} else {
// Iterate through all numbers i less than n.
// Avoid duplicate solutions by ensuring that the partial array is always non-increasing
for (int i=n; i>0; i--) {
if (partial.isEmpty() || partial.get(partial.size()-1) >= i) {
partial.add(i);
partition(n-i, partial, partitions);
partial.remove(partial.size()-1);
}
}
}
}
/**
* Helper method: creates a new integer array and copies the contents of the list into the array.
*/
private static int[] toArray(List<Integer> list) {
int i = 0;
int[] arr = new int[list.size()];
for (int val : list) {
arr[i++] = val;
}
return arr;
}
}
Here's a solution in using paramorphisms that I wrote in Haskell.
import Numeric.Natural (Natural)
import Control.Monad (join)
import Data.List (nub)
import Data.Functor.Foldable (ListF (..), para)
partitions :: Natural -> [[Natural]]
partitions = para algebra
where algebra Nothing = []
algebra (Just (0,_)) = [[1]]
algebra (Just (_, past)) = (nub . (getAll =<<)) (fmap (1:) past)
getAll :: [Natural] -> [[Natural]]
getAll = fmap (dropWhile (==0) . sort) . subsets
where subsets xs = flip sumIndicesAt xs <$> indices xs
indices :: [Natural] -> [[Natural]]
indices = join . para algebra
where algebra Nil = []
algebra (Cons x (xs, [])) = [[x:xs]]
algebra (Cons x (xs, past)) = (:) <$> [x:xs,[]] <*> past
It's definitely not the most efficient one around, but I think it's quite elegant and it's certainly instructive.
here is the java code for this question
static void printArray(int p[], int n){
for (int i = 0; i < n; i++)
System.out.print(p[i]+" ");
System.out.println();
}
// Function to generate all unique partitions of an integer
static void printAllUniqueParts(int n) {
int[] p = new int[n]; // An array to store a partition
int k = 0; // Index of last element in a partition
p[k] = n; // Initialize first partition as number itself
// This loop first prints current partition, then generates next
// partition. The loop stops when the current partition has all 1s
while (true) {
// print current partition
printArray(p, k + 1);
// Generate next partition
// Find the rightmost non-one value in p[]. Also, update the
// rem_val so that we know how much value can be accommodated
int rem_val = 0;
while (k >= 0 && p[k] == 1) {
rem_val += p[k];
k--;
}
// if k < 0, all the values are 1 so there are no more partitions
if (k < 0){
break;
}
// Decrease the p[k] found above and adjust the rem_val
p[k]--;
rem_val++;
while (rem_val > p[k]) {
p[k + 1] = p[k];
rem_val = rem_val - p[k];
k++;
}
p[k + 1] = rem_val;
k++;
}
}
public static void main(String[] args) {
System.out.println("All Unique Partitions of 5");
printAllUniqueParts(5);
System.out.println("All Unique Partitions of 7");
printAllUniqueParts(7);
System.out.println("All Unique Partitions of 9");
printAllUniqueParts(8);
}
Another Java solution. It starts by creating first partition which is only the given number. Then it goes in while loop which is finding the last number in last created partition which is bigger then 1. From that number it moves 1 to next number in array. If next number would end up being the same as the found number it moves to the next in line. Loop stops when first number of last created partition is 1. This works because at all times numbers in all partitions are sorted in descending order.
Example with number 5. First it creates first partition which is just number 5. Then it finds last number in last partition that is greater then 1. Since our last partition is array [5, 0, 0, 0, 0] it founds number 5 at index 0. Then it takes one from 5 and moves it to next position. That is how we get partition [4, 1, 0, 0, 0]. It goes into the loop again. Now it takes one from 4 and moves it up so we get [3, 2, 0, 0, 0]. Then the same thing and we get [3, 1, 1, 0, 0]. On next iteration we get [2, 2, 1, 0, 0]. Now it takes one from second 2 and tries to move it to index 2 where we have 1. It will skip to the next index because we would also get 2 and we would have partition [2, 1, 2, 0, 0] which is just duplicate of the last one. instead we get [2, 1, 1, 1, 0]. And in the last step we get to [1, 1, 1, 1, 1] and loop exists since first number of new partition is 1.
private static List<int[]> getNumberPartitions(int n) {
ArrayList<int[]> result = new ArrayList<>();
int[] initial = new int[n];
initial[0] = n;
result.add(initial);
while (result.get(result.size() - 1)[0] > 1) {
int[] lastPartition = result.get(result.size() - 1);
int posOfLastNotOne = 0;
for(int k = lastPartition.length - 1; k >= 0; k--) {
if (lastPartition[k] > 1) {
posOfLastNotOne = k;
break;
}
}
int[] newPartition = new int[n];
for (int j = posOfLastNotOne + 1; j < lastPartition.length; j++) {
if (lastPartition[posOfLastNotOne] - 1 > lastPartition[j]) {
System.arraycopy(lastPartition, 0, newPartition, 0, lastPartition.length);
newPartition[posOfLastNotOne]--;
newPartition[j]++;
result.add(newPartition);
break;
}
}
}
return result;
}
Here is my Rust implementation (inspired by Python Algorithms and Data Structures):
#[derive(Clone)]
struct PartitionIter {
pub n: u32,
partition: Vec<u32>,
last_not_one_index: usize,
started: bool,
finished: bool
}
impl PartitionIter {
pub fn new(n: u32) -> PartitionIter {
PartitionIter {
n,
partition: Vec::with_capacity(n as usize),
last_not_one_index: 0,
started: false,
finished: false,
}
}
}
impl Iterator for PartitionIter {
type Item = Vec<u32>;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None
}
if !self.started {
self.partition.push(self.n);
self.started = true;
return Some(self.partition.clone());
} else if self.n == 1 {
return None;
}
if self.partition[self.last_not_one_index] == 2 {
self.partition[self.last_not_one_index] = 1;
self.partition.push(1);
if self.last_not_one_index == 0 {
self.finished = true;
} else {
self.last_not_one_index -= 1;
}
return Some(self.partition.clone())
}
let replacement = self.partition[self.last_not_one_index] - 1;
let total_replaced = replacement + (self.partition.len() - self.last_not_one_index) as u32;
let reps = total_replaced / replacement;
let rest = total_replaced % replacement;
self.partition.drain(self.last_not_one_index..);
self.partition.extend_from_slice(&vec![replacement; reps as usize]);
if rest > 0 {
self.partition.push(rest);
}
self.last_not_one_index = self.partition.len() - (self.partition.last().cloned().unwrap() == 1) as usize - 1;
Some(self.partition.clone())
}
}

Resources