I’ve been doing the Perl Weekly
Challenges. The
latest
involved searching arrays and summing tree paths.
You are given an array @N of positive integers (sorted) and another
non negative integer k.
Write a script to find if there exists 2 indices i and j such that
A[i] - A[j] = k and i != j.
It should print the pairs of indices, if any such pairs exist.
Example:
@N = (2, 7, 9)
$k = 2
Output : 2,1
This feels like someone's computer science homework. But it's simple
enough in O(N²); if the numbers were unique I could optimise by
sticking them into hash keys and seeing whether the hash entry for
(k-N[i]) existed, but that's not a guarantee given here.
my @N = (2, 7, 9);
my $k = 2;
my @out;
foreach my $j (0..$#N-1) {
foreach my $i ($j+1..$#N) {
if ($N[$i]-$N[$j] == $k) {
push @out,[$i,$j];
}
}
}
foreach (@out) {
print "$_->[0], $_->[1]\n";
}
Perl6 lets me get rid of the references but is otherwise the same.
You are given a binary tree and a sum, write a script to find if the tree has a path such that adding up all the values along the path equals the given sum. Only complete paths (from root to leaf node) may be considered for a sum.
Example
Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 9
/ \ \
7 2 1
For the given binary tree, the partial path sum 5 → 8 → 9 = 22 is not valid.
The script should return the path 5 → 4 → 11 → 2 whose sum is 22.
The interesting part here is not the actual path walking but the
representation of the tree. Since I know I only want to walk it
downwards, I only care about the descendants of any particular node.
My input representation uses leading . to indicate depth.
use List::Util qw(sum);
my @tree=qw(5 .4 ..11 ...7 ...2 .8 ..13 ..9 ...1);
# 0 1 2 3 4 5 6 7 8
my $target=22;
my %tree;
{
my @parent;
foreach my $index (0..$#tree) {
$tree[$index] =~ /^(\.*)(\d+)/;
my ($depth,$val)=(length($1),$2);
$tree{$index}{value}=$val;
if ($depth>0) {
push @{$tree{$parent[$depth-1]}{children}},$index;
}
$parent[$depth]=$index;
}
}
Now that we have the tree, a standard breadth-first search
implemented as a ring buffer will solve the nominal problem. (I could
optimise by storing the sum of the path so far in the path entry, but
scaling up isn't one of the requirements of the problem.)
my @paths=([0]);
while (@paths) {
my $p=shift @paths;
if (exists $tree{$p->[-1]}{children}) {
foreach my $x (@{$tree{$p->[-1]}{children}}) {
push @paths,[@{$p},$x];
}
} else {
if (sum(map{$tree{$_}{value}} @{$p}) == $target) {
print join(' -> ',map{$tree{$_}{value}} @{$p}),"\n";
}
}
}
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.