This code is taken from the Go heap example (with my own added prints). Here's the playground.
https://play.golang.org/p/E69SfBIZF5X
Most everything is straightforward and makes sense, but the one thing I can't wrap around is why the 'minimum' print on index 0 of the heap in main() returns the value 1 (the correct minimum) but printing 4 in the heap's pop function returns 1 (see output).
If the root (minimum) of a heap is always at n=0, why is it n=4 in the pop function itself? It then seems to work fine, in descending order.
Can someone explain what's going on here? I don't feel comfortable implementing something like the Pop before I understand what's going on.
// This example demonstrates an integer heap built using the heap interface.
package main
import (
"container/heap"
"fmt"
)
// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
// Push and Pop use pointer receivers because they modify the slice's length,
// not just its contents.
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
fmt.Printf("n: %v\n", n)
fmt.Printf("x: %v\n", x)
return x
}
// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
h := &IntHeap{2, 1, 5}
heap.Init(h)
heap.Push(h, 3)
fmt.Printf("minimum: %d\n", (*h)[0])
for h.Len() > 0 {
fmt.Printf("roll: %d\n", (*h)[0])
fmt.Printf("%d\n", heap.Pop(h))
}
}
-
Output
x = value
n = index
minimum: 1
roll: 1
n: 4
x: 1
1
roll: 2
n: 3
x: 2
2
roll: 3
n: 2
x: 3
3
roll: 5
n: 1
x: 5
5
The textbook heap algorithms include a way to fix up a heap if you know the entire heap structure is correct (a[n] < a[2*n+1] && a[n] < a[2*n+2], for all n in bounds), except that the root is wrong, in O(lg n) time. When you heap.Pop() an item, it almost certainly (*IntHeap).Swaps the first and last elements, does some more swapping to maintain the heap invariants, and then (*IntHeap).Pops the last element. That's what you're seeing here.
You can also use this to implement a heap sort. Say you have an array int[4] you're trying to sort. Take a slice s int[] = (a, len=4, cap=4), then:
If len(s) == 1, stop.
Swap s[0] and s[len(s)-1].
Shrink the slice by one item: s = (array(s), len=len(s)-1, cap=cap(s)).
If the heap is out of order, fix it.
Go to 1.
Say your example starts with [1, 2, 5, 3]. Then:
[1, 2, 5, 3]
[3, 2, 5, 1] Swap first and last
[3, 2, 5], 1 Shrink slice by one
[2, 3, 5], 1 Correct heap invariant
[5, 3, 2], 1 Swap first and last
[5, 3], 2, 1 Shrink slice by one
[3, 5], 2, 1 Correct heap invariant
[5, 3], 2, 1 Swap first and last
[5], 3, 2, 1 Shrink slice by one
5, 3, 2, 1 Sorted (descending order)
You need to climb a staircase that has n steps, and you decide to get some extra exercise by jumping up the steps. You can cover at most k steps in a single jump. Return all the possible sequences of jumps that you could take to climb the staircase, sorted.
My implementation is obviously giving me the wrong answer.
def climbingStaircase(n, k):
final_res=[]
final_res.append(CSR(n,k,[]))
return final_res
def CSR(n,k,res):
if n == 0:
return res
else:
for i in range(1,k+1):
if n-i>=0:
res.append(i)
n=n-i
res=CSR(n,i,res)
return res
For n = 4 and k = 2, the output should be
[[1, 1, 1, 1],
[1, 1, 2],
[1, 2, 1],
[2, 1, 1],
[2, 2]]
Actual output:
[[1,1,1,1,2,1]]
Can someone point out which part I'm missing?
One huge problem is in the code below: you deduct the quantity of steps for each possibility within the step range.
n=n-i
res=CSR(n,i,res)
When you're done exploring what you can do with a 1-step jump, you need to backtrack and try from the same starting point (this instance's original value of n) with a 2-step jump. Change the code to:
res = CSR(n-i, i, res)
This keeps the n value intact as you go through the loop.
In addition, you can't limit future jumps to the max of what you just took. Change that second parameter, too:
res = CSR(n-i, k, res)
That should get you moving. Also try this lovely debug blog for help. At least insert one or two tracing statements, such as
print n, k, res
at the top of your routine.
CAVEAT
This is not all of your trouble. The largest remaining problem is that CSR returns only one solution: every step you take is appended to the same list. You need a way to gather the completed solutions as separate lists; the append in climbingStaircase is executed only once, after CSR is entirely finished.
You need to recognize a completed solution at n==0.
DEBUGGING HELP
Here is a version of your program with the recursion parameters fixed, and debugging traces inserted.
indent = ""
def climbingStaircase(n, k):
final_res = []
final_res.append(CSR(n, k, []))
return final_res
def CSR(n, k, res):
global indent
indent += " "
print indent, n, k, res
if n == 0:
print "SOLUTION", res
else:
for i in range(1, k+1):
if n-i >= 0:
CSR(n-i, k, res + [i])
indent = indent[:-2]
print climbingStaircase(4, 2)
Note the use of "indent" to help visualize your recursion and backtracking. The critical part here is that, instead of updating res globally, I've left it as a local variable. I've also removed the return value for now, simply dumping to output the solutions as they're found. You can see how it works:
4 2 []
3 2 [1]
2 2 [1, 1]
1 2 [1, 1, 1]
0 2 [1, 1, 1, 1]
SOLUTION [1, 1, 1, 1]
0 2 [1, 1, 2]
SOLUTION [1, 1, 2]
1 2 [1, 2]
0 2 [1, 2, 1]
SOLUTION [1, 2, 1]
2 2 [2]
1 2 [2, 1]
0 2 [2, 1, 1]
SOLUTION [2, 1, 1]
0 2 [2, 2]
SOLUTION [2, 2]
[None]
With this stuff in place, I'm hopeful you can trace your logic and figure out how to capture the sequence of solutions at a level of your choosing.
Successfully implemented Prune's answer.
def climbingStaircase(n, k):
res=[]
CSR(n,k,[],res)
return res
def CSR(n,k,str_, res):
if n == 0:
res.append(str_)
else:
for i in range(1,k+1):
if n-i>=0:
CSR(n-i,k,str_+[i],res)
A quick Java version of this solution:
int[][] climbingStaircase(int n, int k) {
List<ArrayList<Integer>> list = new ArrayList<>();
climb(n, k, new ArrayList<Integer>(), list);
// convert to int[][]
int[][] result = new int[list.size()][];
for (int i=0; i<list.size(); i++) {
List<Integer> l = list.get(i);
int [] arr = new int[l.size()];
for (int j=0; j<l.size(); j++)
arr[j] = l.get(j);
result[i] = arr;
}
return result;
}
void climb(int n, int k, ArrayList<Integer> prev, List<ArrayList<Integer>> list) {
if (n==0) { // no more stairs, done climbing
list.add(prev);
} else {
for (int i=1; i<=k; i++) { // climb remaining stairs in intervals from 1 to k steps
if (i <= n) { // no need to test intervals larger than remaining # of stairs
ArrayList<Integer> branch = new ArrayList<>(prev);
branch.add(i);
climb(n-i, k, branch, list);
}
}
}
}
In Swift 5.5
func solution(n: Int, k: Int) -> [[Int]] {
var res_final = [[Int]]()
SRC(n: n, k: k, res: [], &res_final)
return res_final
}
var indent: String = ""
func SRC(n: Int, k: Int, res: [Int], _ res_final: inout [[Int]]) {
indent += " "
print(indent, n, k, res)
if n == .zero {
res_final.append(res)
print("Solution", res)
} else {
for i in 1...k {
if n-i >= .zero {
SRC(n: n-i, k: k, res: res + [i], &res_final)
}
}
}
indent = " "
}
solution(n: 4, k: 2)
I'm looking to explore different algorithms, both recursive and dynamic programming, that checks if one arrayA is a subsequence of arrayB. For example,
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
thus, arrayA is indeed a subsequence of arrayB.
I've tried a few different searches, but all I can seem to find is algorithms to compute the longest increasing subsequence.
Since you must match all elements of arrayA to some elements of arrayB, you never need to backtrack. In other words, if there are two candidates in arrayB to match an element of arrayA, you can pick the earliest one, and never retract the choice.
Therefore, you do not need DP, because a straightforward linear greedy strategy will work:
bool isSubsequence(int[] arrayA, int[] arrayB) {
int startIndexB = 0;
foreach (int n in arrayA) {
int next = indexOf(arrayB, startIndexB , n);
if (next == NOT_FOUND) {
return false;
}
startIndexB = next+1;
}
return true;
}
As dasblinkenlight has correctly said(and i could not have phrased it better than his answer!!) a greedy approach works absolutely fine. You could use the following pseudocode (with just a little more explanation but totally similar to what dasblinkenlight has written)which is similar to the merging of two sorted arrays.
A = {..}
B = {..}
j = 0, k = 0
/*j and k are variables we use to traverse the arrays A and B respectively*/
for(j=0;j<A.size();){
/*We know that not all elements of A are present in B as we
have reached end of B and not all elements of A have been covered*/
if(k==B.size() && j<A.size()){
return false;
}
/*we increment the counters j and k both because we have found a match*/
else if(A[j]==B[k]){
j++,k++;
}
/*we increment k in the hope that next element may prove to be an element match*/
else if(A[j]!=B[k]){
k++;
}
}
return true; /*cause if we have reached this point of the code
we know that all elements of A are in B*/
Time Complexity is O(|A|+|B|) in the worst case, where |A| & |B| are the number of elements present in Arrays A and B respectively. Thus you get a linear complexity.
As #sergey mentioned earlier, there is no need to do backtracking in this case.
Here just another Python version to the problem: [Time complexity: O(n) - worst]
>>> A = [1, 2, 3]
>>> B = [5, 6, 1, 7, 8, 2, 4, 3]
>>> def is_subsequence(A, B):
it = iter(B)
return all(x in it for x in A)
>>> is_subsequence(A, B)
True
>>> is_subsequence([1, 3, 4], B)
False
>>>
Here is an example in Ruby:
def sub_seq?(a_, b_)
arr_a = [a_,b_].max_by(&:length);
arr_b = [a_,b_].min_by(&:length);
arr_a.select.with_index do |a, index|
arr_a.index(a) &&
arr_b.index(a) &&
arr_b.index(a) <= arr_a.index(a)
end == arr_b
end
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
puts sub_seq?(arrayA, arrayB).inspect #=> true
Here is an example in GOLANG...
func subsequence(first, second []int) bool {
k := 0
for i := 0; i < len(first); i++ {
j := k
for ; j < len(second); j++ {
if first[i] == second[j] {
k = j + 1
break
}
}
if j == len(second) {
return false
}
}
return true
}
func main(){
fmt.Println(subsequence([]int{1, 2, 3}, []int{5, 1, 3, 2, 4}))
}
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())
}
}