Related
I am trying to learn linked list.I am learning from other people code. What I am trying to do is I am trying to console.log in many places. But the thing is the code does not work in my VSO.
Here is code working in leet code but not in my VSO.Why?
//* Definition for singly-linked list.
function ListNode(val, next) {
this.val = (val===undefined ? 0 : val)
this.next = (next===undefined ? null : next)
/**
* #param {ListNode} l1
* #param {ListNode} l2
* #return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
var List = new ListNode(0);
var head = List;
var sum = 0;
var carry = 0;
while(l1!==null||l2!==null||sum>0){
if(l1!==null){
sum = sum + l1.val;
l1 = l1.next;
}
if(l2!==null){
sum = sum + l2.val;
l2 = l2.next;
}
if(sum>=10){
carry = 1;
sum = sum - 10;
}
head.next = new ListNode(sum);
head = head.next;
sum = carry;
carry = 0;
}
return List.next;
};
addTwoNumbers([2, 4, 3], [5, 6, 4]);
I'm trying the leetcode remove elements problem. The goal is to remove all the elements from an array equal to a certain value. For example if the array = [3, 2, 2, 3] and the val = 3 the output array should be [2, 2].
My filter function seems to be producing the correct output based on the console log, but in the return statement it is something totally different.
Below is a copy of my code:
/**
* #param {number[]} nums
* #param {number} val
* #return {number}
*/
var removeElement = function(nums, val) {
let filteredNums = nums.filter(element => {
return element !== val
});
console.log(filteredNums)
return filteredNums;
};
Here is what I am getting for the output:
Is there something I am doing incorrect that I am missing?
By assuming to remove elements form the array, you could use a different approach by splicing the array.
By using Array#splice, you need to iterate from the end of the array, because the index is changing for deleted elements.
Finally you need to return the new length of the array.
/**
* #param {number[]} nums
* #param {number} val
* #return {number}
*/
var removeElement = function(nums, val) {
let i = nums.length;
while (i--) if (nums[i] === val) nums.splice(i, 1);
return nums.length;
};
var array = [3, 2, 2, 3];
console.log(removeElement(array, 3));
console.log(array);
Nina's answer is very good;
We can also solve the problem without using built-in functions – especially for easy LeetCode questions that's somewhat important (for interviews, not the contests):
const removeElement = function(nums, val) {
let lo = 0;
let hi = nums.length - 1;
while (lo <= hi) {
if (nums[lo] === val) {
swap(nums, lo, hi);
hi -= 1;
} else {
lo += 1;
}
}
return lo;
};
const swap = function(nums, left, right) {
const temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
return nums;
};
// console.log(removeElement(nums = [3,2,2,3], val = 3));
Disclaimer:
Don't know JavaScript well;
Well, it works as intended:
const removeElement = function(nums, val) {
let filteredNums = nums.filter(element => {
return element !== val
});
console.log("From inside of the function:", filteredNums)
return filteredNums;
};
const exampleArray = [3, 2, 2, 3];
const element = 3;
console.log("Original array before:", exampleArray)
const result = removeElement(exampleArray, element);
console.log("Returning array:", result);
console.log("Original array after:", exampleArray)
One thing that may trip you up is the fact that filteredNums is not changing the incoming array, instead it returns a copy of the original array without filtered out elements.
Question:
Merge two sorted linked lists and return it as a new sorted list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
My solution:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* #param {ListNode} l1
* #param {ListNode} l2
* #return {ListNode}
*/
var mergeTwoLists = function(l1, l2, l3) {
if (l2 === null) {
l3.next = l1;
return l3;
}
if (l1 === null) {
l3.next = l2;
return l3;
}
if (l2.val < l1.val) {
if (l3) {
l3.next = new ListNode(l2.val)
}
else {
l3 = new ListNode(l2.val)
}
return mergeTwoLists(l1, l2.next, l3)
} else {
if (l3) {
l3.next = new ListNode(l1.val);
}
else {
l3 = new ListNode(l1.val);
}
return mergeTwoLists(l1.next, l2, l3)
}
};
My output is just 1->4 instead of 1->1->2->3->4->4. Can anyone please tell me why?
The main cause of the problems you encounter is in the third parameter that your function has: this is not in line with the description of the challenge. There is no third parameter. You need to create the returned list without such a value.
I understand that you have tried to pass a partial result as the third argument, and want to extend that partial result in each recursive call, but then things go wrong:
First, in the first two if blocks you assume that l3 is not null, but you cannot be sure of that. In case the input consists of an empty list, your code will produce an exception.
Secondly, if l3 represents a list that has more than one element, then this code will overwrite the existing link between l3 and l3.next, and so the original l3.next (and all the nodes that follow) will get lost.
Although you can solve this, by first finding the terminating node in l3, there is a better way. And this better way is actually a core principle in well designed recursion:
If possible, don't pass a partial result to the recursive call with the aim to extend that partial result to a final result. Instead try to make the function in such a way, that it does not need any such partial result from the caller, but can do its work on the input as if that was the very original input. The caller should use the returned value to treat that as a partial result, and extend it before returning that to its caller.
function ListNode(val, next) {
this.val = (val===undefined ? 0 : val)
this.next = (next===undefined ? null : next)
}
var mergeTwoLists = function(l1, l2) { // Only 2 parameters
if (l2 === null) return l1; // don't prepend anything
if (l1 === null) return l2; // don't prepend anything
let node;
if (l2.val < l1.val) {
node = new ListNode(l2.val);
node.next = mergeTwoLists(l1, l2.next);
} else {
node = new ListNode(l1.val);
node.next = mergeTwoLists(l1.next, l2);
}
return node;
};
// Helper function for demo
const listFromArray = a => a.length ? new ListNode(a[0], listFromArray(a.slice(1)))
: null;
let l1 = listFromArray([1, 2, 4]);
let l2 = listFromArray([1, 3, 4]);
console.log(mergeTwoLists(l1, l2));
You can use a Sentinel Node so that it'd be much easier:
const mergeTwoLists = function(l1, l2) {
const sentinel = {
val: -1,
next: null
}
let head = sentinel
while (l1 && l2) {
if (l1.val > l2.val) {
head.next = l2
l2 = l2.next
} else {
head.next = l1
l1 = l1.next
}
head = head.next
}
head.next = l1 || l2
return sentinel.next
}
If you'd like to do recursively, we won't be needing an l3:
const mergeTwoLists = function(l1, l2) {
if (l1 === null) {
return l2
}
if (l2 === null) {
return l1
}
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2)
return l1
} else {
l2.next = mergeTwoLists(l1, l2.next)
return l2
}
}
Your answer is returning only 1->4 because you are not iterating your newly created merged list i.e l3. You are directly doing l3.next=somevalue. Since l3 is a list you first need to iterate over it and add the value or list in its last node where l3.next will be null.
Here is the code which should give you the desired result
function ListNode(val, next) {
this.val = (val === undefined ? 0 : val)
this.next = (next === undefined ? null : next)
}
var mergeTwoLists = function(l1, l2, l3) {
let addToMergedList = (l3, val) => {
let rootNode = l3
while (l3.next !== null)
l3 = l3.next;
l3.next = new ListNode(val);
return rootNode;
}
if (l2 === null) {
let root = l3
if(!root)
return l1
while (l3.next)
l3 = l3.next;
l3.next = l1;
return root;
}
if (l1 === null) {
let root = l3
if(!root)
return l2
while (l3.next)
l3 = l3.next;
l3.next = l2;
return root;
}
if (l2.val < l1.val) {
if (l3) {
l3 = addToMergedList(l3, l2.val)
} else {
l3 = new ListNode(l2.val)
}
return mergeTwoLists(l1, l2.next, l3)
} else {
if (l3) {
l3 = addToMergedList(l3, l1.val)
} else {
l3 = new ListNode(l1.val);
}
return mergeTwoLists(l1.next, l2, l3)
}
};
let l1={val:1,next:{val:2,next:{val:4,next:null}}}
let l2={val:1,next:{val:3,next:{val:4,next:null}}
console.log(mergeTwoLists(l1, l2))
I'm not sure what this or arguments applies to in curry function, since arguments binds to hosting function, in which case that is "a" which I don't belief actually gets used anywhere.
var _isPlaceholder = require('./_isPlaceholder');
/**
* Optimized internal one-arity curry function.
*
* #private
* #category Function
* #param {Function} fn The function to curry.
* #return {Function} The curried function.
*/
module.exports = function _curry1(fn) {
return function f1(a) {
if (arguments.length === 0 || _isPlaceholder(a)) {
return f1;
} else {
return fn.apply(this, arguments);
}
};
};
var _curry1 = require('./internal/_curry1');
/**
* Creates a new object from a list key-value pairs. If a key appears in
* multiple pairs, the rightmost pair is included in the object.
*
* #func
* #memberOf R
* #since v0.3.0
* #category List
* #sig [[k,v]] -> {k: v}
* #param {Array} pairs An array of two-element arrays that will be the keys and values of the output object.
* #return {Object} The object made by pairing up `keys` and `values`.
* #see R.toPairs, R.pair
* #example
*
* R.fromPairs([['a', 1], ['b', 2], ['c', 3]]); //=> {a: 1, b: 2, c: 3}
*/
module.exports = _curry1(function fromPairs(pairs) {
var result = {};
var idx = 0;
while (idx < pairs.length) {
result[pairs[idx][0]] = pairs[idx][1];
idx += 1;
}
return result;
});
The use of arguments here simply allows more than one argument to be applied to the function, while ensuring at least one non-placeholder argument is provided.
The binding of this just ensures that the underlying function is called with the same this that the curried functions is evaluated with.
I have the following data:
var data = [
{ index : 1, sort : 10, parent : 0 },
{ index : 2, sort : 7, parent : 0 },
{ index : 3, sort : 15, parent : 1 },
{ index : 4, sort : 4, parent : 0 },
{ index : 5, sort : 13, parent : 1 },
{ index : 6, sort : 20, parent : 5 },
{ index : 7, sort : 2, parent : 8 },
{ index : 8, sort : 6, parent : 5 },
];
How do I efficiently sort this by both parent ID and the sort value so that I end up with:
var data = [
{ index : 4, sort : 4, parent : 0 },
{ index : 2, sort : 7, parent : 0 },
{ index : 1, sort : 10, parent : 0 },
{ index : 5, sort : 13, parent : 1 },
{ index : 8, sort : 6, parent : 5 },
{ index : 7, sort : 2, parent : 8 },
{ index : 6, sort : 20, parent : 5 },
{ index : 3, sort : 15, parent : 1 },
];
This is a tree structure. Each element is immediately followed by any children and all elements on the same branch are sorted by the sort value.
The best I can come up with is to first sort by parent and then do a second sort on each branch. This seems inefficient.
Edit: The example sort order was wrong. I've corrected it.
Edit for clarification: Each nested branch needs to appear immediately below the parent value, not at the end of the branch.
Edit: further corrections to data.
This is not your original approach, but you could build an actual tree from your data, like this:
function TreeNode(data) {
this.data = data;
this.parent = null;
this.children = [];
}
TreeNode.comparer = function (a, b) {
return a.data.sort < b.data.sort ? 0 : 1;
};
TreeNode.prototype.sortRecursive = function () {
this.children.sort(TreeNode.comparer);
for (var i=0, l=this.children.length; i<l; i++) {
this.children[i].sortRecursive();
}
return this;
};
function toTree(data) {
var nodeById = {}, i = 0, l = data.length, node;
nodeById[0] = new TreeNode(); // that's the root node
for (i=0; i<l; i++) { // make TreeNode objects for each item
nodeById[ data[i].index ] = new TreeNode(data[i]);
}
for (i=0; i<l; i++) { // link all TreeNode objects
node = nodeById[ data[i].index ];
node.parent = nodeById[node.data.parent];
node.parent.children.push(node);
}
return nodeById[0].sortRecursive();
}
With this set-up, you will get your nodes neatly nested with a simple call:
var tree = toTree(data);
TreeNode:0
parent -> null
data -> undefined
childen -> Array[
TreeNode:1
parent -> TreeNode:0
data -> { index : 4, sort : 4, parent : 0 }
childen -> Array[]
TreeNode:2
parent -> TreeNode:0
data -> { index : 2, sort : 7, parent : 0 }
childen -> Array[]
TreeNode:3
parent -> TreeNode:0
data -> { index : 1, sort : 10, parent : 0 }
childen -> Array[
TreeNode:4
parent -> TreeNode:3
data -> { index : 5, sort : 13, parent : 1 }
childen -> Array[
]
TreeNode:5
parent -> TreeNode:3
data -> { index : 3, sort : 15, parent : 1 }
childen -> Array[
... and so on ...
]
]
]
Once you have that tree object, you can do a number of things with it, including traversing it recursively in the expected order.
To do this, you could add a helper function that does depth-first traversal and executes a payload function f for every node:
TreeNode.prototype.walk = function(f, recursive) {
for (var i=0, l=this.children.length; i<l; i++) {
var child = this.children[i];
f.apply(child, Array.prototype.slice.call(arguments, 2));
if (recursive) child.walk.apply(child, arguments);
}
}
and call it like this:
tree.walk(function () { console.log(this.data) }, true);
which would produce:
{ index: 4, sort: 4, parent: 0}
{ index: 2, sort: 7, parent: 0}
{ index: 1, sort: 10, parent: 0}
{ index: 5, sort: 13, parent: 1}
{ index: 8, sort: 6, parent: 5}
{ index: 7, sort: 2, parent: 8}
{ index: 6, sort: 20, parent: 5}
{ index: 3, sort: 15, parent: 1}
Use more complex payload functions for other effects, like adding table rows in a table with jQuery or items to a <select> box.
Tomalak request above that I post my singleton version of their answer. Here it is:
/**
* Represents sorted results in a tree structure.
*/
Tree = (function() {
/**
*
* #type {Object} nodes Holds all the nodes in a flat format.
* #type {Object} nodes.data The data that is held in this node.
* #type {Object} nodes.parent Points to the parent object of this node.
* #type {Array} nodes.children An array of the child nodes of this node.
*/
var nodes = {};
/**
* #type {Object} root_node A Reference to the root node in nodes.
*/
var root_node;
/**
* A sort function to sort the nodes by the data.sort value in each node.
* #param {Number} a The first node to compare
* #param {Number} b The second node to compare
* #return {Boolean} Swap these nodes or not.
*/
var comparer = function (a, b) {
return a.data.sort < b.data.sort ? 0 : 1;
};
/**
* Sorts all the nodes so that they are in the correct order according to each nodes data.sort value.
* #param {Object} node A reference to the node in the nodes object.
*/
var sortRecursive = function (node) {
node.children.sort(comparer);
var len = node.children.length;
for (var i = 0 ; i < len ; i++) {
sortRecursive(node.children[i]);
}
};
/**
* Create a new node with the passed in data.
* #param {Object} data The data that is associated with this node.
*/
var create_node = function(data){
var node = {
data : data,
parent : null,
children : []
};
return node;
};
return {
/**
* Create a new tree of data
* #param {Array} data An array of data objects to transorm into a tree.
* #param {Array} data[].index The id of this node
* #param {Array} data[].parent The parent id of this node.
* #param {Number} root_id Id of the root node.
*/
create : function(data, root_id){
// Clear any previous data
nodes = {};
var i;
var len = data.length;
// Create an empty root node
nodes[root_id] = create_node({});
root_node = nodes[root_id];
// Make node objects for each data item
for (i=0; i<len; i++) {
if(typeof data[i].sort !== "undefined")
nodes[ data[i].index ] = create_node(data[i]);
}
// Link all TreeNode objects
for (i=0; i<len; i++) {
var node = nodes[data[i].index];
node.parent = nodes[node.data.parent];
node.parent.children.push(node);
}
sortRecursive(nodes[root_id]);
},
/**
* Walk through the nodes in nested and then sorted order, calling the passed in callback for each node.
* #param {Function} callback A callback function to call for each node.
* #param {Boolean} recursive Should the walkback be recursive, or just fetch the top level results.
* #param {Object|Undefined} node The node that is currently being walked.
* Ommit this value and the root node will be used.
*/
walk : function(callback, recursive, node) {
if(typeof node == "undefined")
node = root_node;
for (var i = 0, len = node.children.length; i < len; i++) {
var child = node.children[i];
callback.apply(child, Array.prototype.slice.call(arguments, 2));
if (recursive)
arguments.callee(callback, recursive, child);
}
}
};
})();
Populate the tree with:
Tree.create(unsorted_data, parent_id);
Fetch a sorted array with:
var sorted = [];
Tree.walk(function(){
sorted.push(this.data);
}, true);
After many attempts I've come up with this. It works, but is not very elegant. Could also do with abstracting into its own class.
// Initial sort places items in the correct sort order.
data.sort(function(a, b) {
return a.sort - b.sort;
});
vat top_parent_id = 1; // The value of an items parent if it is a top level item.
var sorted = []; // Empty array to copy sorted elements into.
var skipped = true; // flag to indicate if any elements have been skipped.
var skip_count = 0; // Counter to prevent infinite loops.
// Loop until no elements have been skipped.
//This loops through each level of the tree until all nested branches have been added
while(skipped){
skipped = false;
skip_count++;
if(skip_count === 50){ // Maximum tree depth.
throw "Error in sorted data or tree depth too great.";
break;
}
// Loop through the data in reverse order; this preserves the branch sort order.
for (var i = data.length - 1; i >= 0; i--) {
var item = data[i];
// Skip if this element has already been processed.
if(item.done)
continue;
// If this is this a top level item, then insert and continue.
if(item.parent == top_parent_id){
sorted.splice(0, 0, item); // Insert at the start; last item is the top sort.
item.done = true;
continue;
}
// Loop the new array to try and find this items parent.
var found = false;
for (var j = 0; j < sorted.length; j++) {
if(item.parent === sorted[j].index){
sorted.splice(j + 1, 0, item);
found = true;
item.done = true;
break;
}
}
// If a place for an item has not been found then skip it for now so it can be tested again on the next iteration.
if(!found){
skipped = true;
}
}
}
data = sorted;
Edit: ditch this, it doesn't work.
This is the best I've managed. Which should bubble sort it. I've not tested it yet. I'll leave the best answer open to see if anyone can improve on it.
data.sort(function(a, b) {
return a.parent - b.parent;
});
var changes = true;
while (changes){
changes = false;
for (var i = 1; i < data.length; i++) {
if(data[i].parent === data[i-1].parent && data[i].sort < data[i-1].sort){
var tmp = data[i-1];
data[i-1] = data[i];
data[i] = tmp;
changes = true;
}
}
}