I have a graph, each node have 4 child nodes. I wrote a algorithm to generate a random path from a begin node to an end node. At each node, it chooses a random next node. Visited node can be revisited.
the code is like the following:
public List<Node> GetPath(Node begin, Node end)
{
var nodes = new List<Node>();
var node = begin;
while (node != end)
{
nodes.Add(node);
var next = node.Children[new Random().Next(4)];
node = next;
}
nodes.Add(end);
return nodes;
}
But sometimes, the Random does not work as expected. The "new Random().Next(4)" keeps generating 0. So it is always the first child node get chose and a very long repeat sequence like node1->node2->node1->node2... is generated and eventually an out of memory exception happens.
Is there a way to make the Random class works correctly?
The reason is because Random is initialized based on the current time (there is no true random in computers... only psuedo-random). The while loop iterates too quickly, and the system time has not registered a change. So you're re-initializing a new Random object that starts with the same value.
Try creating one Random object that is reused throughout the method:
public List<Node> GetPath(Node begin, Node end)
{
var nodes = new List<Node>();
var node = begin;
Random r = new Random();
while (node != end)
{
nodes.Add(node);
var next = node.Children[r.Next(4)];
node = next;
}
nodes.Add(end);
return nodes;
}
Initialize Random instance outside loop, e.g.:
public List<Node> GetPath(Node begin, Node end)
{
var nodes = new List<Node>();
var node = begin;
var random = new Random();
while (node != end)
{
nodes.Add(node);
var next = node.Children[random.Next(4)];
node = next;
}
nodes.Add(end);
return nodes;
}
You mention that the method is being called upon in multiple threads. A solution is to have one random number generartor per thread that is seeded by a static rng.
I've also removed the constant 4 and changed it to node.Children.Count.
static Random seed = new Random();
[ThreadLocal] static Random rng;
public List<Node> GetPath(Node begin, Node end)
{
var nodes = new List<Node>();
var node = begin;
if (rng == null)
rng = new Random(seed.Next());
while (node != end)
{
nodes.Add(node);
var next = node.Children[rng.Next(node.Children.Count)];
node = next;
}
nodes.Add(end);
return nodes;
}
There are a few things working against you here. The first is that you're expecting a different number every time you ask for one, but that's not what this class does nor is it the definition of random. So, this class is in fact working correctly.
Definition of Random
Made, done, happening, or chosen without method or conscious decision: "a random sample of 100 households".
Governed by or involving equal chances for each item.
Now, this class does its best at giving each option an equal opportunity at being chosen. So, when you think of random make sure you're putting into context the definition of the term. However, remember that this class does not work like the human mind.
Now, to address the fact that you're getting zero very frequently, it's happening for two reasons. First, you are creating a new Random class in every iteration. But more importantly, your range is too small because you're expecting it to give you a different number every time on a range of only 4 options, and since it's pseudo-random just as MSDN states you're getting the same answer frequently.
I realize the reason you're only giving it 4 options, but I think you might need to reconsider the type of functionality you're looking for because it would probably lead to less frustration.
Related
This is a leetcode problem.
I saw the solution however while trying to use my own logic, I cannot iterate over to the next node.
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
try
{
string l1NodeData = null;
string l2NodeData = null;
do
{
l1NodeData = l1NodeData + l1.val;
l1 = l1.next;
} while (l1 != null);
do
{
l2NodeData = l2NodeData + l2.val;
l2 = l2.next;
} while (l2 != null);
int sum = Convert.ToInt32(l1NodeData) + Convert.ToInt32(l2NodeData);
var sumInChar = sum.ToString().ToArray();
ListNode dummyhead = new ListNode(0);
ListNode ans = dummyhead;
for (int i = sumInChar.Length - 1; i > 0; i--)
{
ans.val = Convert.ToInt32(sumInChar[i].ToString());
ListNode tempListNode = new ListNode(Convert.ToInt32(sumInChar[i - 1].ToString()));
ans.next = tempListNode;
ans = ans.next;
//here(ans = ans.next) after assigning the next node, the data of the current node is getting overridden.
}
return ans;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
In the above solution where I am assigning ans = ans.next, there the current node is overridden with the next node, however, I just want to move to the next node in order to iterate.
Could someone please help me on this?
In the above solution where I am assigning ans = ans.next, there the current node is overridden with the next node, however, I just want to move to the next node in order to iterate.
The assignment is to a variable. That never mutates your linked list. This way of assigning to a variable is exactly what you need to traverse a linked list. It does not modify it. In order to mutate it, you will always need to assign to a member (property) of a node, like its next property.
In the code comments you wrote:
the data of the current node is getting overridden.
No, it looks like that because you return the reference to the last node that was created in the loop. Instead you should return dummyHead.next; This way you return the first node that was created in the loop.
In comments you wrote:
...I have not made any assignment to dummyhead right, then how does data reside in that variable?
You have referenced ans to the same node as dummyHead, and you did assign to ans.next, which in the first iteration of the loop is synonymous to dummyHead.next. With those assignments to ans.next the nodes get linked to eachother.
Note that dummyHead is an extra node that is created to ease the code in the loop -- not having to make a special case for creating the real head node. After the loop that dummyHead is then ignored (it served its purpose), and the real head (that is sitting right after it) is returned.
Inside the class Test, there must be a public method getLinkedList and it shall receive nothing, but answer with a Node object.
You must create the Node class inside the Test class and it must be public. The Node class must have two instance variables. One that holds numbers and have the name TAL and one that holds a Node object and have the name NEXT.
Calling the getLinkedList the first time, it must answer with a Node object that has the TAL=1 and the NEXT=null
Calling the getLinkedList the second time, it must answer with a Node object that has the TAL=2 and the NEXT points to a Node with the TAL=1. This means that the first Node is placed last in the list and the newest Node is always at the front and its TAL value is the same as the numbers of Nodes in the list.
This is what I've done so far. Don't give me the answer direct please.
public Node getLinkedList()
{
Node n = new Node();
n.TAL = 1;
n.NEXT = null;
Node n1 = new Node();
n1.TAL = 2;
n.NEXT.TAL = n.TAL;
}
public class Node
{
public int TAL;
public Node NEXT;
}
Alright without giving you too much, here's what you need to do with your get linked list function.
public Node GetLinkedList()
{
//Check if your linked list is empty
//If yes return your TAL = 1 node
//If no create a new node with new TAL and return that
}
This should get you pointed in the right direction at least. You need some conditional logic in there
I have a recursion function that builds a node list from an IEnumerable of about 2000 records. The procedure currently takes around 9 seconds to complete and has become a major performance issue. The function serves to:
a) sort the nodes hierarchically
b) calculate the depth of each node
This is a stripped down example:
public class Node
{
public string Id { get; set; }
public string ParentId { get; set; }
public int Depth { get; set; }
}
private void GetSortedList()
{
// next line pulls the nodes from the DB, not included here to simplify the example
IEnumerable<Node> ie = GetNodes();
var l = new List<Node>();
foreach (Node n in ie)
{
if (string.IsNullOrWhiteSpace(n.ParentId))
{
n.Depth = 1;
l.Add(n);
AddChildNodes(n, l, ie);
}
}
}
private void AddChildNodes(Node parent, List<Node> newNodeList, IEnumerable<Node> ie)
{
foreach (Node n in ie)
{
if (!string.IsNullOrWhiteSpace(n.ParentId) && n.ParentId == parent.Id)
{
n.Depth = parent.Depth + 1;
newNodeList.Add(n);
AddChildNodes(n, newNodeList, ie);
}
}
}
What would be the best way to rewrite this to maximize performance? I've experimented with the yield keyword but I'm not sure that will get me the result I am looking for. I've also read about using a stack but none of the examples I have found use parent IDs (they use child node lists instead), so I am a little confused on how to approach it.
Recursion is not what is causing your performance problem. The real problem is that on each recursive call to AddChildNodes, you traverse the entire list to find the children of the current parent, so your algorithm ends up being O(n^2).
To get around this, you can create a dictionary that, for each node Id, gives a list of all its children. This can be done in a single pass of the list. Then, you can start with the root Id ("") and recursively visit each of its children (i.e. a "depth first traversal"). This will visit each node exactly once. So the entire algorithm is O(n). Code is shown below.
After calling GetSortedList, the sorted result is in result. Note that you could make children and result local variables in GetSortedList and pass them as parameters to DepthFirstTraversal, if you prefer. But that unnecessarily slows down the recursive calls, since those two parameters would always have the same values on each recursive call.
You can get rid of the recursion using stacks, but the performance gain would probably not be worth it.
Dictionary<string, List<Node>> children = null;
List<Node> result = null;
private void GetSortedList()
{
var ie = data;
children = new Dictionary<string,List<Node>>();
// construct the dictionary
foreach (var n in ie)
{
if (!children.ContainsKey(n.ParentId))
{
children[n.ParentId] = new List<Node>();
}
children[n.ParentId].Add(n);
}
// Depth first traversal
result = new List<Node>();
DepthFirstTraversal("", 1);
if (result.Count() != ie.Count())
{
// If there are cycles, some nodes cannot be reached from the root,
// and therefore will not be contained in the result.
throw new Exception("Original list of nodes contains cycles");
}
}
private void DepthFirstTraversal(string parentId, int depth)
{
if (children.ContainsKey(parentId))
{
foreach (var child in children[parentId])
{
child.Depth = depth;
result.Add(child);
DepthFirstTraversal(child.Id, depth + 1);
}
}
}
I want to build a tree structure like this:
root Id 1
child id 2
grandChild id 3
Code sample below. If I use GetChildrenNodesCorrect(), I get the correct result. But when GetChildrenNodesWrong() is used, it returns below:
root Id 1
child id 2
Null
I know that ToList() is not deferred execution, and returns result immediatelly. Could anyone explain this?
public class ToListTest
{
public static void Entry()
{
var toListTest = new ToListTest();
toListTest.Test();
}
public void Test()
{
List<Node> newsList = new List<Node>
{
new Node{Id = 1, ParentId = 0},
new Node{Id = 2, ParentId = 1},
new Node{Id = 3, ParentId = 2}
};
var root = BuildUpTree(newsList);
}
private TreeNode BuildUpTree(List<Node> newsList)
{
var root = new TreeNode { currentNode = newsList.First(n => n.ParentId == 0) };
BuildUpTreeChildrenNodes(newsList, root);
return root;
}
private void BuildUpTreeChildrenNodes(List<Node> newsList, TreeNode currentTreeNode)
{
currentTreeNode.Children = GetChildrenNodesWrong(newsList, currentTreeNode);
foreach (var node in currentTreeNode.Children)
{
BuildUpTreeChildrenNodes(newsList, node);
}
}
private IEnumerable<TreeNode> GetChildrenNodesWrong(List<Node> newsList, TreeNode cuurentNode)
{
return newsList.Where(n => n.ParentId == cuurentNode.currentNode.Id)
.Select(n => new TreeNode
{
currentNode = n
});
}
private IEnumerable<TreeNode> GetChildrenNodesCorrect(List<Node> newsList, TreeNode cuurentNode)
{
return GetChildrenNodesWrong(newsList, cuurentNode).ToList();
}
public class TreeNode
{
public Node currentNode { get; set; }
public IEnumerable<TreeNode> Children { get; set; }
}
public class Node
{
public int Id { get; set; }
public int ParentId { get; set; }
}
}
Update
In debug, when using GetChildrenNodesWrong(), root has both child and grandchild before the method returns. After the method returns, root has only child, and grandchild is null.
Update 2
IMO, the problem might not be related to clean code. But anyone is welcome to show more intuitive code.
Every time the IEnumerable is evaluated the Linq query is re-executed. So, when you're computing the tree, it is allocating space for nodes but not assigning them to any permanent variable. This means that in the foreach loop in BuildUpTreeChildrenNodes, you are not calling the recursive function on the instance of the node you want. Instead, you're calling it on a re-instantiated version of the node that has been created by the foreach loop (which enumerates the IEnumerable). When you call ToList on the IEnumerable instead, then the foreach loop will return the elements of the list, which is in memory.
If you make root public static, and then debug your code, you'll see that when you call BuildUpTreeChildrenNodes, the node argument is not the instance of the node that you want. Even though it has the same ID and represents the same node in the graph, it is not actually connected in any way to the root node. Check:
root.Children.Any(n => n.Id == node.Id) //true
root.Children.Contains(node) //false
The simplest way to see your problem is here:
//Create a singleton Node list:
var nodeSingleton= Enumerable.Range(0, 1).Select(x => new Node { Id = x });
Console.Write(nodeSingleton.Single() == nodeSingleton.Single());
You might expect this to return true, but in fact it will be false - both times the Single Linq method is called, the deferred execution of the singleton variable is re-evaluated, and returns a different instance of the Node class.
If you call ToList on the singleton, however, then you get the list in memory and the Single method will return the same instance of the Node.
More broadly, I think the problem with this code is that it mixes up imperative and functional code too much. It is strange that so many of the methods are void and then the GetChildrenNodesWrong method is not. I think you should pick a style and stick with it, since switching paradigms can be confusing.
I'm not entirely sure what you're asking. All LINQ queries have deferred execution, when you call ToList() you're simply forcing the query to execute. I think the main problem is in your where clause. Only two objects satisfy the condition so the IEnumerable returned by your LINQ query should only have 2 objects.
It's not doing what you expect because the LINQ query in GetChildrenNodesWrong is producing an "off by one" error. Here is basically what happens;
1) we feed it root for n = root nothing happens. We move to the next node.
2) n.Id = 1, the where condition is met by node 2 as it's parentId is 1. We allocate a new node, point current to node 2
3) We get to the third node now. n.ParentId = 2 and current.Id = 2. We have a match so we allocated another node and point current to node 3.
4) we're at the end of the list. Grand child is never allocated because we're off by one.
Basically you iterate x time where x is the length of the list but because current = n on the first iteration you don't allocate a node so you end up with x -1 nodes when you're expecting x.
I'm trying to populate hierarchical data in a .NET 2.0 (yes, 2.0) application and upgrading right now is off the table (so no LINQ, LINQ Bridge, or other things).
I was wondering if there is a better way to populate hierarchical data into this class structure? I'm pretty sure there is a far better way for this to be accomplished.
It would be really nice to see a good way to do this. If anyone has the time to show a .NET 2.0 way and if there is a different way they would do it in .NET 4.0+ that would be great.
Here is an example of the node type structure:
using System.Collections.Generic;
public class ExampleNode
{
private int _id;
private Nullable<int> _parentId;
private int _depth;
private List<ExampleNode> _children = new List<ExampleNode>();
public ExampleNode()
{
}
public virtual int ApplicationNumber {
get { return _id; }
set { _id = value; }
}
public virtual Nullable<int> ParentId {
get { return _parentId; }
set { _parentId = value; }
}
public virtual int Depth {
get { return _depth; }
set { _depth = value; }
}
public virtual List<ExampleNode> Children {
get { return _children; }
set { _children = value; }
}
}
Here is an example function that is being utilized to populate the node structure. It seems like it is not the best way to do this and it has the potential not to populate grandchildren type data. Depth comes back from the stored proc as the level in the hierarchy (items with a level of 0 are top level, if a node is the child of a top level node it is at level 1, a grandchild of a top level node is level 2, etc.)
public List<ExampleNode> GetNodes()
{
// This may not be optimal.
List<ExampleNode> nodeList = new List<ExampleNode>();
Dictionary<int, ExampleNode> nodeDictionary = new Dictionary<int, ExampleNode>();
using (SqlDataReader reader = SqlHelper.ExecuteReader(ConfigurationManager.ConnectionStrings("SqlServer").ConnectionString, CommandType.StoredProcedure, "proc_GetNodeStructure", new SqlParameter("#UserId", userId), new SqlParameter("#NodeTypeId", nodeType))) {
while (reader.Read) {
ExampleNode nodeInstance = new ExampleNode();
nodeInstance.Id = Convert.ToInt32(reader("Id"));
nodeInstance.Depth = Convert.ToInt32(reader("Depth"));
if (!Information.IsDBNull(reader("ParentId"))) {
nodeInstance.ParentId = Convert.ToInt64(reader("ParentId"));
}
// Add to list
nodeList.Add(nodeInstance);
// Add to dictionary
nodeDictionary.Add(nodeInstance.Id, nodeInstance);
}
}
foreach (ExampleNode item in nodeList) {
if (item.ParentId.HasValue) {
nodeDictionary(item.ParentId).Children.Add(item);
}
}
for (int i = nodeList.Count - 1; i >= 0; i += -1) {
if (nodeList(i).Depth > 0) {
nodeList.RemoveAt(i);
}
}
return nodeList;
}
If I understand correctly, you
gather the nodes into a list and a dictionary
iterate through the list and arrange parent/child relationships via the dictionary
remove nodes from the list that have a positive depth
... which leaves the list containing the top-most nodes in the hierarchical stucture. Your algorithm seems correct to me.
The first two operations are O(n) complexity in time and space with respect to the number of nodes, which is pretty good!
The only real inefficient thing you are doing is removing elements from the list in step 3. Because the underlying storage is a vector, removing an element from the front of the list is expensive, because all of the remaining elements need to be copied down. You are trying to minimize the amount of such copying by iterating over the list backward. Imagine that the last half of the list is parent nodes, and the front half is child nodes. Whenever you remove a child node, you will still have to copy half the original list size every time a child node is removed. This approaches O(n^2) behaviour.
So for step 3 you have at least two choices if you wish to improve performance in time:
Make a second list that contains only the elements from the first where the depth == 0.
Use a linked list instead, so that deletions are O(1) instead of up to O(n) performance.
Here is the code for the first option:
...
List<ExampleNode> roots = new List<ExampleNode>();
for (int i = 0; i < nodeList.Count; i ++) {
if (nodeList[i].Depth == 0) {
roots.Add(nodeList[i]);
}
}
return roots;
You could potentially save even a little more time by counting how many root nodes there are during step 1 or 2, and then initializing the second list so its capacity is equal to the number of root nodes. This will prevent unnecessary allocations and copying of the underlying list vector while you are adding elements to the list.
List<ExampleNode> roots = new List<ExampleNode>(rootCount);
The same applies to the first nodeList; you can delay its construction until you know the number of records returned from the query.
What about using NHibernate? It works with .net 2 plus, so you can move forward with it as well.