I am trying to solve a problem which is: Find all ancestors of a particular node in a binary tree.
Input: root, targetNode
Output: An array/list containing the ancestors
Suppose, we have the above binary tree as an example. We want to find the ancestors of the node 4. The output should be [3, 5, 2, 4]. If the node is 8, the output is [3, 1, 8]
To solve this, I have written a function which implements DFS.
var ancestor = function(root, target) {
var isFound = false;
const dfs = (node, curr) => {
if (node === null) {
return curr;
}
if (node.val === target.val) {
curr.push(node.val);
isFound = true;
return curr;
}
curr.push(node.val);
const left = dfs(node.left, curr);
if (!isFound) {
const right = dfs(node.right, curr);
curr.pop();
return right;
} else {
curr.pop();
return left;
}
}
console.log(dfs(root, []));
};
But it is not returning the correct ouput. For example, if the targetNode is 7, the output is [3], if the targetNode is 8, the output is also [3]. If I remove the line curr.pop() the output is also invalid. for targetNode 7 it is [3 , 5, 6, 2, 7]. I think I found the issue where I am making mistake. While backtracking, I am doing something wrong with the remove of the node that was pushed in the curr array. If I pass a string instead of the array, it prints the output correctly.
var ancestor = function(root, target) {
var isFound = false;
const dfs = (node, curr) => {
if (node === null) {
return curr;
}
if (node.val === target.val) {
curr += node.val;
isFound = true;
return curr;
}
const left = dfs(node.left, curr + node.val + '->);
if (!isFound) {
const right = dfs(node.right, curr + node.val + '->);
return right;
} else {
return left;
}
}
console.log(dfs(root, ''));
The above code with string instead of array prints the output correctly, If I pass targetNode 7, output is 3->5->2->7
My question is, how to properly unchoose/backtrack here? Or is there anything else that I am doing incorrectly? Thanks in advance.
recursion in its natural setting
Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding imperative things such as mutations like push and cur += node.val, variable reassignments like isFound = true, and other side effects. We can write ancestor as a simple generator-based function that prepends each node to the output of recursive sub-problem -
const empty =
Symbol("tree.empty")
function node(val, left = empty, right = empty) {
return { val, left, right }
}
function* ancestor(t, q) {
if (t == empty) return
if (t.val == q) yield [t.val]
for (const l of ancestor(t.left, q)) yield [t.val, ...l]
for (const r of ancestor(t.right, q)) yield [t.val, ...r]
}
const mytree =
node(3, node(5, node(6), node(2, node(7), node(4))), node(1, node(0), node(8)))
for (const path of ancestor(mytree, 7))
console.log(path.join("->"))
3->5->2->7
use modules
To finish, I would recommend a module-based approach for this code -
// tree.js
const empty =
Symbol("tree.empty")
function node(val, left = empty, right = empty) {
return { val, left, right }
}
function* ancestor(t, q) {
if (t == empty) return
if (t.val == q) yield [t.val]
for (const l of ancestor(t.left, q)) yield [t.val, ...l]
for (const r of ancestor(t.right, q)) yield [t.val, ...r]
}
function insert(t, val) {
// ...
}
function remove(t, val) {
// ...
}
function fromArray(a) {
// ...
}
// other tree functions...
export { empty, node, ancestor, insert, remove, fromArray }
// main.js
import { node, ancestor } from "./tree.js"
const mytree =
node(3, node(5, node(6), node(2, node(7), node(4))), node(1, node(0), node(8)))
for (const path of ancestor(mytree, 7))
console.log(path.join("->"))
3->5->2->7
private generator
In the previous implementation, our module exposes a generator for ancestor's public interface. Another option is to return undefined when a node cannot be found and has no ancestry. Consider this alternate implementation which hides the generator and requires the caller to null-check the result instead -
const empty =
Symbol("tree.empty")
function node(val, left = empty, right = empty) {
return { val, left, right }
}
function ancestor(t, q) {
function* dfs(t) {
if (t == empty) return
if (t.val == q) yield [t.val]
for (const l of dfs(t.left)) yield [t.val, ...l]
for (const r of dfs(t.right)) yield [t.val, ...r]
}
return Array.from(dfs(t))[0]
}
const mytree =
node(3, node(5, node(6), node(2, node(7), node(4))), node(1, node(0), node(8)))
const result =
ancestor(mytree, 7)
if (result)
console.log(result.join("->"))
else
console.log("no result")
3->5->2->7
You need to check whether the DFS of the right child has found the node.
fix:
const left = dfs(node.left, curr);
if (!isFound) {
const right = dfs(node.right, curr);
if(isFound) {
return right;
}
curr.pop();
return; // return nothing, backtracking
}
return left;
In the array example, your loop iterates through the nodes in a DFS manner, so each of those nodes are connected in that manner. If we count the tree nodes in DFS algorithm, [3 , 5, 6, 2, 7] are actually in order 1, 2, 3, 4 and 5. In this manner, your whole tree in an array should be looking like this; [3 , 5, 6, 2, 7, 4, 1, 0, 8].
So when you find the target value, you pop from the current node and trace it all back up to the head node in DFS algorithm.
I'd either suggest finding a way to get around that, or you could save each of these node's parents. Meaning you could use tuples instead of int arrays (if that's acceptable). An index could look like this = (node value, parent value)
[(3,NULL),(5,3),(6,5),(2,5)...]
And then traceback accordingly...
Related
I am trying to find the K-th largest element in a Binary Search Tree using reverse inorder approach by using a counter. Here is what I have implemented:
int klargest(Node root,int k,int count)
{
if(root != null)
{
klargest(root.right,k,count);
count++;
if(count == k)
return root.data;
klargest(root.left,k,count);
}
return -1;
}
But the issue is that when count = k, the code does not return the answer to the caller function but instead to a sub-call. Due to this, the answer is lost. In other words, the recursion does not stop there and it keeps on going until all the nodes are visited. In the end, I get the answer -1. What I want is that the recursion should end when count = k and the required answer should be returned to the caller function. How can I do this?
Note: I neither want to use a global variable nor an iterative approach.
Actually, you do not return your node - the recursive call results are ignored. Rewrite it so it returns a Node:
Node klargest(Node root,int k,int count)
{
Node result = null;
if(root != null)
{
result = klargest(root.right,k,count);
if (result != null)
return result;
count++;
if(count == k)
return root;
result = klargest(root.left,k,count);
}
return result;
}
You can use this approach:
int kthLargest(Node node, int k) {
int rightCount = count(node.right);
if (k <= rightCount) {
return kthLargest(node.right, k);
} else if (k == rightCount+1) {
return node.data;
} else {
return kthLargest(node.left, k - rightCount + 1);
}
}
int count(Node node) {
if (node != null) {
return count(node.left) + count(node.right) + 1;
}
return 0;
}
I have multiple overlapping squares in Paper.js, and I'd like to separate all the overlapping shapes into their own. You can do exactly this in Illustrator with the pathfinder divide. Before I attempt to just loop through all overlapping shapes and divide them with each other with what might have to be some nested loops I think, I'm wondering if there's a better way.
Example in Illustrator
I want to turn all these squares:
https://i.imgur.com/PPRi9M9.png
into pieces like this
https://i.imgur.com/xTFS8jP.png
(moved the pieces away from each other so you can see how they're separated)
I ended up going with my own solution which sounded more practical and simple than #arthur's answer. Not sure about which would be more performant though. To summarize, I map what blocks are overlapping with each other with a nested loop and Path.intersects(path), then do another nested loop to divide each block with its overlapping blocks with Path.divide(path) which will cut the original path with whatever path you're dividing it with.
Here's my actual code I'm using in my project with comments.
setupGrid() {
// Setup block row and column positions
for (let i = 0;i < this.total;i++) {
let x
let y
if (!odd(i)) {
x = firstColumnStartX + (this.size/2)
y = firstColumnStartY + ((i/2) * (this.size + this.gap)) + (this.size/2)
} else {
x = secondColumnStartX + (this.size/2)
y = secondColumnStartY + (Math.floor(i/2) * (this.size + this.gap)) + (this.size/2)
}
this.blocks.push(new paper.Path.Rectangle({
position: [x, y],
size: this.size,
strokeColor: '#ff000050'
}))
}
// Setup array to check what blocks are intersecting
const intersects = []
// Setup empty array with a nested array mapped to other blocks [5 x [5 x undefined]]
for (let i = 0;i < this.total;i++) {
intersects[i] = new Array(this.total).fill(undefined)
}
// Intersect checking
for (let i = 0;i < this.total;i++) {
const block = this.blocks[i]
for (let _i = 0;_i < this.total;_i++) {
const otherBlock = this.blocks[_i]
if (block !== otherBlock && intersects[i][_i] === undefined) {
intersects[_i][i] = intersects[i][_i] = block.intersects(otherBlock)
}
}
}
// First loop through all blocks
for (let i = 0;i < this.total;i++) {
let block = this.blocks[i]
// Then loop through other blocks only if they were intersected with the original block
for (let _i = 0;_i < this.total;_i++) {
const otherBlock = this.blocks[_i]
if (intersects[i][_i]) {
/* divide returns {
pieces: array of separated pieces that would be inside the original block's boundaries
leftoverBlock: what's leftover of the other block if the original block was subtracted from it
} */
const divide = this.divide(block, otherBlock)
block.remove()
otherBlock.remove()
// Override current block with the array of pieces
block = this.blocks[i] = divide.pieces
// Override other block with leftover
this.blocks[_i] = divide.leftoverBlock
// Don't let other block divide with original block since we already did it here
intersects[_i][i] = undefined
}
}
}
// Set random color for each piece to check if successful
for (let i = 0;i < this.blocks.length;i++) {
let block = this.blocks[i]
if (block instanceof Array) {
for (let _i = 0;_i < block.length;_i++) {
block[_i].fillColor = new paper.Color(Math.random(), Math.random(), Math.random(), 0.1)
}
} else {
block.fillColor = new paper.Color(Math.random(), Math.random(), Math.random(), 0.1)
}
}
}
// Divide blockA with blockB and expand
divideBlocks(blockA, blockB, pieces = []) {
const divideA = blockA.divide(blockB)
if (divideA instanceof paper.CompoundPath) {
for (let i = divideA.children.length;i--;) {
const child = divideA.children[i]
child.insertAbove(divideA)
pieces.push(child)
}
divideA.remove()
} else {
pieces.push(divideA)
}
return pieces
}
// Divide group (array of paths) with divider
divideGroup(children, divider, pieces = [], parent) {
for (let i = children.length;i--;) {
const child = children[i]
if (parent) {
child.insertAbove(parent)
}
if (child.intersects(divider)) {
this.divideBlocks(child, divider, pieces)
} else {
pieces.push(child)
}
}
}
// Subtract group (array of paths) from block
subtractGroupFromBlock(block, group) {
let oldBlock
let newBlock = block
for (let i = group.length;i--;) {
const child = group[i]
if (child.intersects(block)) {
newBlock = newBlock.subtract(child)
if (oldBlock) {
oldBlock.remove()
}
oldBlock = newBlock
}
}
return newBlock
}
// Check what kind of divide method to use
divide(blockA, blockB) {
const pieces = []
let leftoverBlock
if (blockA instanceof paper.Path) {
this.divideBlocks(blockA, blockB, pieces)
leftoverBlock = blockB.subtract(blockA)
} else if (blockA instanceof Array) {
this.divideGroup(blockA, blockB, pieces)
leftoverBlock = this.subtractGroupFromBlock(blockB, blockA)
}
return {
pieces,
leftoverBlock
}
}
My blocks set with random colors to differentiate each shape:
Overlapping blocks before:
https://i.imgur.com/j9ZSUC5.png
Overlapping blocks separated into pieces:
https://i.imgur.com/mc83IH6.png
Since you want to create shapes which did not exist before (according to your example, you want the operation to create the inner rectangle), I think you will have to loop over all overlapping shapes, compute intersections with Path.getIntersections(path[, include]), and re-create new paths from existing ones.
Once you computed all intersections, you will have to loop through all vertices, always rotating in the same direction, and create the new paths.
Take one (random) vertex, find the connected vertex "with the smallest angle" (it should work with currentVertex.getDirectedAngle(connectedVertex)) ; set the current vertex as visited and continue until you find the first vertex again. Create a shape, and redo this algorithm until you visited all vertices.
You could also use Path.intersect(path[, options]) but I don't think it would help you.
I've written a algorithm to find parameters in a command line tool and are looking to clean up my code but is stuck.
The task
My program receives parameters as: flag output input ... | input flag output
Examples are: -d one/path second/path/to/file.txt and second/path/to/file.txt --dir one/path etc. Each space is used as a delimiter to create an array of parameters. A parameter can be either a flag such as -d or a path.
I got each flag mapped out in two arrays, which I zip into a an array of tuples. I call them the search set.
In math notation
I'm new to both FP and math notations so please forgive my mistakes (I've learned from wikipedia and other sites).
S for search and P for parameters
S = { S₁, S₂, S₃ }
where Sn = { flagShort, flagLong }
where flagShort = '-d' | '-r' | '-o'
flagLong = '--dir' | '--replace' | '--output'
P = { P₁, P₂, ... }
where Pn = flag | path
where path = dir | file
So I need to find the output by searching P for occurrences of Sn + the next parameter after the flag.
Ps = Sn ∩ P + Pₙ+₁
Input is just Ps ∉ P, so that is easy if I can get Ps.
Which leads me to the following transformation:
P -> Pn -> S -> Sn -> Sn = Pn -> Pn + Pₙ+₁
In javascript it can be written as:
const flagsShort = ["-r","-d","-o"]
const flagsLong = ["--replace","--dir","--output"]
const search = _.zip(flagsShort, flagsLong)
let Ps = tuplesIntersectionParametersPlusNextP(
['one/path', '--dir', 'two/path', '-d', 'one/path', '-d'],
search
)
// Ps -> [ '--dir', 'two/path', '-d', 'one/path' ]
function tuplesIntersectionParametersPlusNextP(P, S) {
const Ps = [];
P.forEach( (Pn, n) => {
S.forEach(Sn => {
Sn.forEach(flag => {
if(flag===Pn) Ps.push(Pn, P[n+1])
})
})
})
return Ps
}
While the code above works, it doesn't look clean. I've been looking around for different FP libraries such as underscore and different python articles but have yet to figure out how to use all these clever FP functions to clean up my code.
I will accept an answer in any language, Python, Haskell, Scala, etc but please don't use list comprehensions. While I'm very confident that I can port your code to js, I find list comprehensions a tad difficult to port. Better use map each reduce etc.
If you also can point me in the right direction with the set notations, I will be truly grateful!
Disclaimer
I tend to stay away from Javascript. There might be nicer ways to do certain things in Javascript, but I believe that the general principles still hold.
Your code is fine, albeit nested a little deep.
The trick in making your code cleaner is to extract abstract functionality. In the deepest nesting, what you're really asking is "does element Pn exist in the list of lists S?" This is something I can imagine myself asking more than once in an application, so it's perfect to turn into a function. You could even make this recursive for any level of nesting:
function ElementInNestedLists(e, l) {
if (l instanceof Array) {
return l.reduce(function(prev, cur, idx, arr) {
if (prev || ElementInNestedLists(e, cur)) {
return true;
}
return false;
}, false);
} else {
return l == e;
}
}
You don't have to use reduce here. There's nothing forbidding you from doing an actual for-loop in functional programming, in languages that support it. This does a better job at preventing the function from continuing after your element has been found:
function ElementInNestedLists(e, l) {
if (l instanceof Array) {
for (elem of l) {
if (ElementInNestedLists(e, elem)) {
return true;
}
}
return false;
} else {
return l == e;
}
}
Using this new function, you can simplify tuplesIntersectionParametersPlusNextP:
function tuplesIntersectionParametersPlusNextP(P, S) {
const Ps = [];
P.forEach( (Pn, n) => {
if (ElementInNestedLists(Pn, S)) {
Ps.push(Pn, P[n + 1]);
}
});
return Ps;
}
But there's a bug. The output of this function, given your input, is [ '--dir', 'two/path', '-d', 'one/path', _undefined_ ], because the last flag has no parameter following it. We need to add a test to ensure that there are at least two elements remaining to be checked.
function tuplesIntersectionParametersPlusNextP(P, S) {
const Ps = [];
P.forEach( (Pn, n) => {
if (n + 1 < P.length && ElementInNestedLists(Pn, S)) {
Ps.push(Pn, P[n + 1]);
}
});
return Ps;
}
But there's another bug. Consider the input ['-d', '-d', 'foo']. The output would be ['-d', '-d', '-d', 'foo'], which is incorrect. The desired output is ['-d', '-d']. You could decide to add a variable to track whether or not you need to process the next field:
function tuplesIntersectionParametersPlusNextP(P, S) {
const Ps = [];
skip = false;
P.forEach( (Pn, n) => {
if (skip) {
skip = false;
return;
}
if (n+1 < P.length && ElementInNestedLists(Pn, S)) {
Ps.push(Pn, P[n + 1]);
skip = true;
}
})
return Ps
}
And while this does what you want, you've now lost cleanliness again. The solution (as is often the case in functional programming) is to solve this problem recursively.
function Parse(cmd, flags, acc = []) {
if (cmd.length < 2) {
return acc;
}
if (ElementInNestedLists(cmd[0], flags)) {
acc.push(cmd[0], cmd[1]);
return Parse(cmd.slice(2, cmd.length), flags, acc)
}
return Parse(cmd.slice(1, cmd.length), flags, acc)
}
And if you don't want to slice:
function Parse(cmd, flags, idx = 0, acc = []) {
if (idx + 1 >= cmd.length) {
return acc;
}
if (ElementInNestedLists(cmd[idx], flags)) {
acc.push(cmd[idx], cmd[idx + 1]);
return Parse(cmd, flags, idx + 2, acc);
}
return Parse(cmd, flags, idx + 1, acc);
}
Of course, you might want to check and discard — or otherwise handle — a flag following a flag. There might be other, more complex requirements that you either haven't mentioned or haven't thought of (yet), but those are outside the scope of this answer.
Here is what I've done so far:
struct rep_list {
struct node *head;
struct node *tail;
}
typedef rep_list *list;
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
lst->head = lst->head->next;
return 1 + length(lst);
}
}
This works, but the head of the list the function accepts as a parameter gets changed. I don't know how to fix that.
I'm not allowed to change the function definition so it should always accept a list variable.
Any ideas?
EDIT: I tried to do what Tyler S suggested in the comments but I encountered another problem. If I create a node* variable at the beginning, it should point to lst->head. But then every recursive call to the function changes the value back to lst->head and I cannot move forward.
You don't need a local node: just don't change the list head. Instead, pass the next pointer as the recursion head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
return 1 + length(lst->head-next);
}
}
I see. Okay; this gets a bit clunky because of the chosen representation. You need a temporary variable to contain the remaining list. This iscludes changing the head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
new_lst = new(list)
new_lst->head = lst->head->next;
var result = 1 + length(new_lst);
free(new_lst)
return result
}
}
At each recursion step, you create a new list object, point it to the 2nd element of the current list, and continue. Does this do the job for you?
Although this solution is clunky and I hate it, its the only way I can see to accomplish what you're asking without modifying the method signature. We create a temporary node * as member data of the class and modify it when we start.
struct rep_list {
struct node *head;
struct node *tail;
}
node *temp = NULL;
bool didSetHead = false;
typedef rep_list *list;
int length(const list lst) {
if ((didSetHead) && (lst->head != temp)) {
temp = lst->head;
didSetHead = false;
}
if (temp == NULL) {
didSetHead = true;
return 0;
}
else {
temp = temp->next;
return 1 + length(temp);
}
}
Please note, I haven't tested this code and you may have to play with a bit, but the idea will work.
In Dart I've got
typedef List<int> Callback(int n);
StyleCallback get fn {
return (int n) {
return new List.generate(n, (i) {
return i;
});
};
}
I would like to write a getter that gets the result of fn(n) and applies some function f to each element of it. For example, multiplies all elements of the List by 2.
Callback get myFunc {
return Iterable.map(fn, (x) => 2 * x);
}
But there is not such map functions for collections. Could you please suggest the right way to do it?
Not an answer but I can't possibly put this code in a comment.
You can do something like
Iterable iter = [1,2,3,4];
int fn(int x) => x * x;
List<String> get myFunc {
return iter.map((x) => fn(x)).toList();
}
void main() {
print(myFunc);
}
prints
[1, 4, 9, 16]
but I have no idea where your typedef would fit in