This is an interview question, but I don't if there's a best solution for it.
Question: Write a function (in C# or C++) to merge two already sorted linked lists. Given a data structure:
C++:
class Node
{
public:
int data;
Node* next;
};
C#:
class Node
{
public int data;
public Node next;
};
Implement the function:
In C++:
Node* Merge (Node* head1, Node* head2)
{
…
}
In C#:
Node Merge (Node head1, Node head2)
{
…
}
It takes in two already sorted linked lists (in ascendant order) and is supposed to merge them into a single sorted linked list (in ascendant order) and returns the new head. The 2 lists might have nodes with identical data (the int value). We expect the result list doesn’t have identical data.
My solution:
Node Merge(Node head1, Node head2)
{
Node merged = head1;
// Both lists are empty
if (head1 == null && head2 == null)
{
return null;
}
// List 1 is empty
else if (head1 == null && head2 != null)
{
return head2;
}
// List 2 is empty
else if (head2 == null && head1 != null)
{
return head1;
}
// Both lists are not empty
else
{
Node cursor1 = head1;
Node cursor2 = head2;
if (cursor1.next.data > cursor2.data)
{
Node temp = cursor1;
cursor1 = cursor2;
cursor2 = temp;
}
// Add all elements from list 2 to list 1
while (cursor1.next != null && cursor2 != null)
{
if (cursor1.next.data < cursor2.data)
{
cursor1 = cursor1.next;
}
else
{
Node temp1 = cursor1.next;
Node temp2 = cursor2.next;
cursor1.next = cursor2;
cursor2.next = temp1;
cursor1 = cursor1.next;
cursor2 = temp2;
}
}
if (cursor1.next == null)
{
cursor1.next = cursor2;
}
}
// Remove duplicates
head1 = merged;
while (head1.next != null)
{
if (head1.data < head1.next.data)
{
head1 = head1.next;
}
else if (head1.data == head1.next.data)
{
head1.next = head1.next.next;
}
}
return merged;
}
Please give some comments and let me know your smart and good solution. Thank you!
After making sure that I was allowed to use the framework that goes with C#, this is what I would have done.
Given this linked list class (same as yours but using properties)
class Node
{
public int Data { get; set; }
public Node Next { get; set; }
}
Create an IEnumerator for the list
class NodeEnumerator : IEnumerator<int>
{
private Node _current_node;
public NodeEnumerator(Node first) {
_current_node = new Node { Data = 0, Next = first };
}
public int Current {
get { return _current_node.Data; }
}
object IEnumerator.Current {
get { return Current; }
}
public bool MoveNext() {
if (_current_node == null) {
return false;
}
_current_node = _current_node.Next;
return _current_node != null;
}
public void Reset() {
throw new NotSupportedException();
}
public void Dispose() {
}
}
Create the corresponding IEnumerable
class EnumerableNode : IEnumerable<int>
{
private Node _first;
public EnumerableNode(Node first) {
_first = first;
}
public IEnumerator<int> GetEnumerator() {
return new NodeEnumerator(_first);
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
Then use the awesome functions available to me in exchange for this little effort, namely Concat and Distinct
class Program
{
static void Main(string[] args) {
var list1 = new EnumerableNode(
new Node { Data = 1, Next =
new Node { Data = 2, Next =
new Node { Data = 3, Next = null }}});
var list2 = new EnumerableNode(
new Node { Data = 2, Next =
new Node { Data = 3, Next =
new Node { Data = 4, Next = null }}});
var merged = list1.Concat(list2).Distinct();
Console.WriteLine(String.Join(",", list1));
Console.WriteLine(String.Join(",", list2));
Console.WriteLine(String.Join(",", merged));
Console.ReadLine();
}
}
Output
1,2,3
2,3,4
1,2,3,4
The interviewer was probably looking for algorithmics (like your solution), but I think this is more life-like, more elegant, and still shows problem-solving skills, as well as knowledge of the framework and the general concept of enumerators. It works exactly the same in Java, Python and Ruby (and many others I'm sure). I have no idea how it would translate to C++ though.
You might wanna check out how std::merge is implemented:
http://www.cplusplus.com/reference/algorithm/merge/
Related
I am trying to create a linked list function which sorts the list into non-descending order (e.g. 1,2,6,9) and inserts the integer (5) into the correct place (e.g. 1,2,5,6,9).
So far I have created a temporary list to read from and a new list to write to. However, I haven't been able to successfully place the integer into the correct position.
Program console call code
LinkGen<int> link1 = new LinkGen<int>(5);
LinkListGen<int> testList = new LinkListGen<int>();
testList.AddItem(7);
testList.AddItem(6);
testList.AddItem(8);
testList.AddItem(9);
testList.AddItem(16);
testList.InsertInOrder(10);
LinkGen class
class LinkGen<T>
{
private T data;
private LinkGen<T> next;
public LinkGen(T item)
{
data = item;
next = null;
}
public LinkGen(T item, LinkGen<T> list)
{
data = item;
next = list;
}
public LinkGen<T> Next
{
set { this.next = value; }
get { return this.next; }
}
public T Data
{
set { this.data = value; }
get { return this.data; }
}
}
LinkListGen set up
class LinkListGen<T> where T:IComparable
{
private LinkGen<T> list;
public LinkListGen()
{
list = null;
}
AddItem, AppendItem and InsertInOrder Functions
public void AddItem(T item)
{
list = new LinkGen<T>(item, list);
}
public void AppendItem(T item)
{
LinkGen<T> temp = list;
if (temp == null)
list = new LinkGen<T>(item);
else
{
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item);
}
}
public void InsertInOrder(T item)
{
LinkGen<T> temp = list;
LinkListGen<T> newList = new LinkListGen<T>();
if (list == null)
AddItem(item);
else
{
while (list != null)
{
if (item.CompareTo(temp.Data) < 0)
{
newList.AppendItem(item);
}
else
{
newList.AppendItem(temp.Data);
temp = temp.Next;
}
}
//temp.Next = new LinkGen<T>(item);
}
}
(apologies about not originally giving enough code, if more is necessary please let me know)
After entering this while loop, when will list ever equal null again?
while (list != null)
{
if (item.CompareTo(temp.Data) < 0)
{
newList.AppendItem(item);
// and then...?
}
else
{
newList.AppendItem(temp.Data);
temp = temp.Next;
}
// never-ending loop
}
And then you do nothing with locally-scoped newList.
The idea is to find the node that your new node belongs after, then insert it there. The special case is when the new node goes at the head of the list, in which case you need to update your list head reference which you call list.
public void AppendItem(T item)
{
if (list == null)
list = new LinkGen<T>(item);
else {
LinkGen<T> temp = list;
while (temp.Next != null) {
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item);
}
}
public void InsertInOrder(T item)
{
if (list == null || item.CompareTo(list.Data) < 0) {
list = new LinkGen<T>(item) { Next = list };
} else {
LinkGen<T> temp = list;
while (temp.Next != null && !(item.CompareTo(temp.Next.Data) < 0)) {
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item) { Next = temp.Next };
}
}
I tried to implement my linked list below, It just that when I used my linked list, it seems that it's inserting a null entry in the middle. Anyone could take a look? The problem could be in the add end method.
LinkedList<T>
public class LinkedList<T> : IEnumerable<T>
{
public Node<T> Head { get; set; }
public int Count { get; set; }
public LinkedList()
{
Head = new Node<T>();
}
public void AddStart(T data)
{
if (Head == null)
{
Head = new Node<T> {Value = data};
}
else
{
var newNode = new Node<T> {Value = data, Next = Head};
Head = newNode;
}
Count++;
}
public void AddEnd(T data)
{
var newNode = new Node<T> { Value = data, Next = null};
var current = Head;
if (Head == null)
{
Head = newNode;
}
else
{
while (current.Next != null)
{
current = current.Next;
}
current.Next = newNode;
}
}
public IEnumerator<T> GetEnumerator()
{
Node<T> current = Head;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Usage:
LinkedList<string> strings = new LinkedList<string>();
strings.AddStart("a");
strings.AddStart("b");
strings.AddStart("c");
strings.AddEnd("a");
strings.AddEnd("e");
strings.AddEnd("d");
Result: (Notice the null in the middle)
c
b
a
a
e
d
Usage:
LinkedList<string> strings = new LinkedList<string>();
strings.AddStart("a");
strings.AddStart("b");
strings.AddStart("c");
strings.AddEnd("a");
strings.AddEnd("e");
strings.AddEnd("d");
strings.AddStart("a");
strings.AddEnd("b");
strings.AddStart("a");
strings.AddStart("b");
strings.AddStart("c");
strings.AddEnd("a");
strings.AddEnd("e");
strings.AddEnd("d");
Result: (Notice the null in the middle)
c
b
a
a
c
b
a
a
e
d
b
a
e
d
You are creating an empty Node, when you initialize your LinkedList:
public LinkedList()
{
Head = new Node<T>();
}
At this point you essentially have a node without a value. This is displayed as an empty value.
Everytime you call AddStart, you insert items before hand. When calling AddEnd you insert items at the end. Since you call both methods equally, it appears that the initial node is in the middle.
You can resolve this by changing your constructor to this:
public LinkedList()
{
Head = null;
}
Or by removing the constructor alltogether. In both methods you are checking for a Head node with a value, so you do not need to initialize it without a value.
if (Head == null)
{
Head = new Node<T> {Value = data};
}
In your current state, you are checking if Head is null. Head is of Type Node, which, if it is a class, cannot be null, if you initialize it in your constrcutor (Head = new Node<T>(); //not null any longer). So you need to make up your mind on how you want to solve it.
Personally I'd just write a unit test to assert my logic and implementation is correct. If you assume that Head is null after initialisation, test for it:
[Fact]
public void AssertHeadIsNull()
{
var list = new LinkedList<int>();
Assert.Null(list.Head);
}
In your case, the test would have failed, and you could have backtracked the issue to your constructor.
I am trying to reverse a linked list. This is the code I have come up with:
public static void Reverse(ref Node root)
{
Node tmp = root;
Node nroot = null;
Node prev = null;
while (tmp != null)
{
//Make a new node and copy tmp
nroot = new Node();
nroot.data = tmp.data;
nroot.next = prev;
prev = nroot;
tmp = tmp.next;
}
root = nroot;
}
It is working well. Was wondering if it possible to avoid creating new node. Would like to have suggestions on this.
That question gets asked a lot. When I was asked it in my interviews many years ago, I reasoned as follows: a singly-linked list is essentially a stack. Reversing a linked list is therefore a trivial operation on stacks:
newList = emptyList;
while(!oldList.IsEmpty())
newList.Push(oldList.Pop());
Now all you have to do is implement IsEmpty and Push and Pop, which are one or two lines tops.
I wrote that out in about twenty seconds and the interviewer seemed somewhat perplexed at that point. I think he was expecting me to take about twenty minutes to do about twenty seconds work, which has always seemed odd to me.
Node p = root, n = null;
while (p != null) {
Node tmp = p.next;
p.next = n;
n = p;
p = tmp;
}
root = n;
Years ago I missed out on a hipster-L.A.-entertainment-company ASP.NET MVC developer position because I could not answer this question :( (It's a way to weed out non-computer-science majors.) So I am embarrassed to admit that it took me way too long to figure this out in LINQpad using the actual LinkedList<T>:
var linkedList = new LinkedList<int>(new[]{1,2,3,4,5,6,7,8,9,10});
linkedList.Dump("initial state");
var head = linkedList.First;
while (head.Next != null)
{
var next = head.Next;
linkedList.Remove(next);
linkedList.AddFirst(next.Value);
}
linkedList.Dump("final state");
The read-only LinkedListNode<T>.Next property is what makes LinkedList<T> so important here. (Non-comp-sci people are encouraged to study the history of Data Structures---we are supposed to ask the question, Where does the linked list come from---why does it exist?)
You don't need to make a copy. Some pseudo code:
prev = null;
current = head;
next = current->next;
(while next != null)
current->next=prev
prev=current
current=next
next=current->next
This performed pretty well on Leetcode.
public ListNode ReverseList(ListNode head) {
ListNode previous = null;
ListNode current = head;
while(current != null) {
ListNode nextTemp = current.next;
current.next = previous;
previous = current;
current = nextTemp;
}
return previous;
}
Why not just have the head point at the tail, the tail point at the head, and go through the list reversing the direction in which prev points?
If you're not using a head and a tail, just go through the list reversing the prev relationships, and then make head point at the one that had a null prev when you got to it.
public Node ReverseList(Node cur, Node prev)
{
if (cur == null) // if list is null
return cur;
Node n = cur.NextNode;
cur.NextNode = prev;
return (n == null) ? cur : ReverseList(n, cur);
}
Here a sample code to reverse a linked list.
using System;
class Program
{
static void Main(string[] args)
{
LinkItem item = generateLinkList(5);
printLinkList(item);
Console.WriteLine("Reversing the list ...");
LinkItem newItem = reverseLinkList(item);
printLinkList(newItem);
Console.ReadLine();
}
static public LinkItem generateLinkList(int total)
{
LinkItem item = new LinkItem();
for (int number = total; number >=1; number--)
{
item = new LinkItem
{
name = string.Format("I am the link item number {0}.", number),
next = (number == total) ? null : item
};
}
return item;
}
static public void printLinkList(LinkItem item)
{
while (item != null)
{
Console.WriteLine(item.name);
item = item.next;
}
}
static public LinkItem reverseLinkList(LinkItem item)
{
LinkItem newItem = new LinkItem
{
name = item.name,
next = null
};
while (item.next != null)
{
newItem = new LinkItem
{
name = item.next.name,
next = newItem
};
item = item.next;
}
return newItem;
}
}
class LinkItem
{
public string name;
public LinkItem next;
}
linked list reversal recursive
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ReverseLinkedList
{
class Program
{
static void Main(string[] args)
{
Node head = null;
LinkedList.Append(ref head, 25);
LinkedList.Append(ref head, 5);
LinkedList.Append(ref head, 18);
LinkedList.Append(ref head, 7);
Console.WriteLine("Linked list:");
LinkedList.Print(head);
Console.WriteLine();
Console.WriteLine("Reversed Linked list:");
LinkedList.Reverse(ref head);
LinkedList.Print(head);
Console.WriteLine();
Console.WriteLine("Reverse of Reversed Linked list:");
LinkedList.ReverseUsingRecursion(head);
head = LinkedList.newHead;
LinkedList.PrintRecursive(head);
}
public static class LinkedList
{
public static void Append(ref Node head, int data)
{
if (head != null)
{
Node current = head;
while (current.Next != null)
{
current = current.Next;
}
current.Next = new Node();
current.Next.Data = data;
}
else
{
head = new Node();
head.Data = data;
}
}
public static void Print(Node head)
{
if (head == null) return;
Node current = head;
do
{
Console.Write("{0} ", current.Data);
current = current.Next;
} while (current != null);
}
public static void PrintRecursive(Node head)
{
if (head == null)
{
Console.WriteLine();
return;
}
Console.Write("{0} ", head.Data);
PrintRecursive(head.Next);
}
public static void Reverse(ref Node head)
{
if (head == null) return;
Node prev = null, current = head, next = null;
while (current.Next != null)
{
next = current.Next;
current.Next = prev;
prev = current;
current = next;
}
current.Next = prev;
head = current;
}
public static Node newHead;
public static void ReverseUsingRecursion(Node head)
{
if (head == null) return;
if (head.Next == null)
{
newHead = head;
return;
}
ReverseUsingRecursion(head.Next);
head.Next.Next = head;
head.Next = null;
}
}
public class Node
{
public int Data = 0;
public Node Next = null;
}
}
}
Complexity O(n+m). Assuming head is the start node:
List<Node>Nodes = new List<Node>();
Node traverse= root;
while(traverse!=null)
{
Nodes.Add(traverse);
traverse = traverse.Next;
}
int i = Nodes.Count - 1;
root = Nodes[i];
for(; i>0; i--)
{
Nodes[i].Next = Nodes[i-1];
}
Nodes[0].Next=null;
In case you want a ready-made efficient implementation, I created an alternative to LinkedList that supports enumeration and reverse operations. https://github.com/NetFabric/NetFabric.DoubleLinkedList
public class Node<T>
{
public T Value { get; set; }
public Node<T> Next { get; set; }
}
public static Node<T> Reverse<T>(Node<T> head)
{
Node<T> tail = null;
while(head!=null)
{
var node = new Node<T> { Value = head.Value, Next = tail };
tail = node;
head = head.Next;
}
return tail;
}
The definition of ref is unnecessary because if you make the node as a reference type, it is OK to do:
public static void Reverse(Node root)
Also, the beauty of the interview question is less consumption of memory and in place reversal. Maybe a recursive way of doing it is also asked.
I am trying to create a generic doubly linked list , and I am having trouble getting my head around it. Does anyone have an example of a very simple implementation of Doubly Linked List using C#?
Thanks
Below a simple generic double-linked list supporting Add(), an indexer and ToString() - the rest is left as an exercise for the reader - this should give you an idea.
public class LinkedList<T>
{
protected LinkedListNode<T> root = null;
protected LinkedListNode<T> last = null;
public LinkedList()
{
}
public string ToString()
{
StringBuilder sb = new StringBuilder();
var node = root;
while (node != null)
{
sb.Append("{ " + node.Data.ToString() + " } ");
node = node.Next;
}
return sb.ToString();
}
public T this[int index]
{
get
{
var node = GetAt(index);
if(node == null)
throw new ArgumentOutOfRangeException();
return node.Data;
}
set
{
var node = GetAt(index);
if (node == null)
throw new ArgumentOutOfRangeException();
node.Data = value;
}
}
private LinkedListNode<T> GetAt(int index)
{
var current = root;
for(int i=0;i<index;i++)
{
if (current == null)
return null;
current = current.Next;
}
return current;
}
public void Add(T data)
{
if (root == null)
{
root = new LinkedListNode<T>(data);
last = root;
}
else
{
last.Next = new LinkedListNode<T>(data);
last.Next.Previous = last;
last = last.Next;
}
}
}
public class LinkedListNode<T>
{
public T Data {get;set;}
public LinkedListNode(T data)
{
Data = data;
}
public LinkedListNode<T> Next { get; set; }
public LinkedListNode<T> Previous { get; set; }
}
System.Collections.Generic.LinkedList<T> is a generic doubly linked list. You can refer to the MSDN documentation as to how it works and what methods/properties need to be exposed.
In addition to the MSDN Wikipedia and Wikibooks have some very useful information about the structure and form of Doubly Linked Lists.
I was trying to solve one interview question, but for that I have to travel the binary tree level by level. I have designed BinaryNode with having below variable
private object data;
private BinaryNode left;
private BinaryNode right;
Could someone please help to write the BreadthFirstSearch method inside my BinarySearchTree class?
Update: Thanks everyone for your inputs. So this was the interview question.
"Given a binary search tree, design an algorithm which creates a linked list of all the nodes at each depth (i.e., if you have a tree with depth D, you’ll have D linked lists)".
Here is my Method, let me know your expert comment.
public List<LinkedList<BNode>> FindLevelLinkList(BNode root)
{
Queue<BNode> q = new Queue<BNode>();
// List of all nodes starting from root.
List<BNode> list = new List<BNode>();
q.Enqueue(root);
while (q.Count > 0)
{
BNode current = q.Dequeue();
if (current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
list.Add(current);
}
// Add tree nodes of same depth into individual LinkedList. Then add all LinkedList into a List
LinkedList<BNode> LL = new LinkedList<BNode>();
List<LinkedList<BNode>> result = new List<LinkedList<BNode>>();
LL.AddLast(root);
int currentDepth = 0;
foreach (BNode node in list)
{
if (node != root)
{
if (node.Depth == currentDepth)
{
LL.AddLast(node);
}
else
{
result.Add(LL);
LL = new LinkedList<BNode>();
LL.AddLast(node);
currentDepth++;
}
}
}
// Add the last linkedlist
result.Add(LL);
return result;
}
A breadth first search is usually implemented with a queue, a depth first search using a stack.
Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while(q.Count > 0)
{
Node current = q.Dequeue();
if(current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
DoSomething(current);
}
As an alternative to checking for null after dequeuing you can check before adding to the Queue. I didn't compile the code, so it might contain some small mistakes.
A fancier (but slower) version that integrates well with LINQ:
public static IEnumerable<T> BreadthFirstTopDownTraversal<T>(T root, Func<T, IEnumerable<T>> children)
{
var q = new Queue<T>();
q.Enqueue(root);
while (q.Count > 0)
{
T current = q.Dequeue();
yield return current;
foreach (var child in children(current))
q.Enqueue(child);
}
}
Which can be used together with a Children property on Node:
IEnumerable<Node> Children { get { return new []{ Left, Right }.Where(x => x != null); } }
...
foreach(var node in BreadthFirstTopDownTraversal(root, node => node.Children))
{
...
}
var queue = new Queue<BinaryNode>();
queue.Enqueue(rootNode);
while(queue.Any())
{
var currentNode = queue.Dequeue();
if(currentNode.data == searchedData)
{
break;
}
if(currentNode.Left != null)
queue.Enqueue(currentNode.Left);
if(currentNode.Right != null)
queue.Enqueue(currentNode.Right);
}
using DFS approach: The tree traversal is O(n)
public class NodeLevel
{
public TreeNode Node { get; set;}
public int Level { get; set;}
}
public class NodeLevelList
{
private Dictionary<int,List<TreeNode>> finalLists = new Dictionary<int,List<TreeNode>>();
public void AddToDictionary(NodeLevel ndlvl)
{
if(finalLists.ContainsKey(ndlvl.Level))
{
finalLists[ndlvl.Level].Add(ndlvl.Node);
}
else
{
finalLists.Add(ndlvl.Level,new List<TreeNode>(){ndlvl.Node});
}
}
public Dictionary<int,List<TreeNode>> GetFinalList()
{
return finalLists;
}
}
The method that does traversal:
public static void DFSLevel(TreeNode root, int level, NodeLevelList nodeLevelList)
{
if(root == null)
return;
nodeLevelList.AddToDictionary(new NodeLevel{Node = root, Level = level});
level++;
DFSLevel(root.Left,level,nodeLevelList);
DFSLevel(root.Right,level,nodeLevelList);
}