Beginning of loop in doubly linked list? - c++

One question I came across,
In a circular linked list, find node at the beginning of the loop?
EXAMPLE Input: A -> B -> C -> D -> E -> C [the same C as earlier] Output: C
Can one of the solutions be, to see if the address of value stored at these nodes are same?
So something like &(A->value) would return us address and then we find if an address is repeating, if yes that is the beginning of the loop?

You could do so, but this is very not efficient, in terms of space complexity, since you will need to store all nodes you 'saw along the way'.
A better solution would probably be Floyd's cycle finding algorithm, as described in this post

Related

Correct way to add an element to the end of a list?

I was reading on this Haskell page about adding an element to the end of a List.
Using the example, I tried it out for my self. Given the following List I wanted to add the number 56 at the end of it.
Example:
let numbers = [4,8,15,16,23,42]
numbers ++ [56]
I was thrown off by this comment:
Adding an item to the end of a list is a fine exercise, but usually
you shouldn't do it in real Haskell programs. It's expensive, and
indicates you are building your list in the wrong order. There is
usually a better approach.
Researching, I realize that what I'm actually doing is creating a List with 56 as the only element and I'm combining it with the numbers list. Is that correct?
Is using ++ the correct way to add an element to the end of a List?
++ [x] is the correct way to add an element to the end of a list, but what the comment is saying is that you shouldn't add elements to the end of a list.
Due to the way lists are defined, adding an element at the end always requires making a copy of the list. That is,
xs ++ ys
needs to copy all of xs but can reuse ys unchanged.
If xs is just one element (i.e. we're adding to the beginning of a list), that's no problem: Copying one element takes practically no time at all.
But if xs is longer, we need to spend more time in ++.
And if we're doing this repeatedly (i.e. we're building up a big list by continually adding elements to the end), then we need to spend a lot of time making redundant copies. (Building an n-element list in this way is an O(n2) operation.)
If you need to do this, there is usually a better way to structure your algorithm. For example, you can build your list in reverse order (adding elements at the beginning) and only call reverse at the end.
It's the correct way in that all ways of doing it must reduce to at least that much work. The problem is wanting to append to the end of a list at all. That's not an operation that's possible to do efficiently with immutable linked lists.
The better approach is figuring out how to solve your specific problem without doing that. There are a lot of potential approaches. Picking the right one depends on the details of what you're doing. Maybe you can get away with just using laziness correctly. Maybe you are best off generating the list backwards and then reversing it once at the end. Maybe you're best off using a different data structure. It all depends on your specific use case.

How to find the node at the beginning of cycle in linked list? [duplicate]

This question already has answers here:
Finding loop in a singly linked-list
(13 answers)
Closed 4 years ago.
From Cracking the Coding Interview, there is an exercise that says:
Given a circular linked list, implement an algorithm that returns the node at the beginning of the loop.
Definition of circular linked list: A (corrupt) linked list in which a node's next pointer points to an earlier node, so as to make a loop in the linked list.
The algorithmic answer is basically using a slow and fast runner to iterate through the linked list to see if it loops. If the slow and fast runner collide, it loops, so then you find the node at the beginning of the loop. (If they don't collide, then the fast runner will eventually reach the end of the linked list, meaning there is no cycle.)
But the book's answer for finding where the node at the beginning of the loop is relies on the ASSUMPTION that the linked list has a "non-looped" part of size k. Once the slow and fast runners collide, you move the slow runner to the head of the linked list. You iterate both at the same speed until they collide. Where they collide is the node at the beginning of the loop.
My question is, is it possible to find where the node at the beginning of the loop is WITHOUT assuming the linked list has a "non-looped" part of size k? Or do I have to assume that there is a "non-looped" part of size k?
I have 2 answers for this question,
One:
If you have loop inside the list in size k, if you move one of the pointer k steps from the head and another pointer from the head and move them together, finnally when one of them do a full loop, and the another one just start the loop, and then this the reason they both meet at the begining of the loop. all you need is count the nodes on the loop.
Second:
I intreduce my solution by example:
assume we got this list:
find a common pointer using the faster and slower runner method.
let's assume that they meet in node number 7.
after you do it remmber the next pointer of node 7 (as the end of the list).
and for now we can reduction to another problem for solve this problem and that is finding first common element in two linked lists that the end of them is pointer of "node 8", and the head of one of them is the head of the list (node 0) and for the other list head is "node 8".
it's look like this:
you can solve it by the following steps:
1) Get count of the nodes in the first list, let count be c1.
2) Get count of the nodes in the second list, let count be c2.
3) Get the difference of counts d = abs(c1 – c2)
4) Now traverse the bigger list from the first node till d nodes so that from here onwards both the lists have equal no of nodes.
5) Then we can traverse both the lists in parallel till we come across a common node. (Note that getting a common node is done by comparing the address of the nodes).
Unless the book specifically assumes the existence of a positive such k, k can also be zero.
Here's an informal argument for the case k=0:
Assume that the entire list is a loop.
If the fast runner is twice as fast as the slow runner, they will collide when the slow runner has completed one loop, and the fast runner has completed two.
If you then start the slow runner from the beginning again, the two will collide immediately on the first node.
I'm not familiar with that book, but I don't think you read it right. Probably k is the size of the loop, and the algorithm works like this:
Detect a loop using either Floyd's or Brent's algorithm. (both are described here: https://en.wikipedia.org/wiki/Cycle_detection)
Let k be the a multiple of the size of the loop, so that once you're in the loop, you'll get back to the same node if you make k steps. You can measure this after you find the cycle, or you can just count the difference in steps between the "fast pointer" and the "slow pointer" while looking for the cycle.
Put 2 pointers at the head of the list (call them fast and slow again), and advance the "fast" pointer k times.
While the fast and slow pointers point at different nodes, advance them in lock step, so that the fast pointer is always k steps ahead.
The algorithm will stop as soon as the slow pointer gets into the loop -- the first node that can be reached again by advancing through the list.

Why is List.length linear in complexity?

I understand that lists are implemented as singly linked so they don't really have a constant structure that you can pin a length on, but each node should know how many nodes till the last element right? There isn't a way to add a node to some existing list and for that node not to be able to determine the length of the list it represents in constant time provided that the existing nodes already have that info.
I can understand why that wouldn't work in Haskell, for example, due to lazyness, but as far as I know F# lists aren't lazy. So, is the problem just in the extra memory overhead?
Seems to me like typical memory vs time performance consideration.
If standard f# list had the implementation You suggest, then it would need much more place in memory (consider one million long list of bools). And everyone using such list would have to deal with it. There would be no simple way to opt out of this other than writing completely new implementation of list.
On the other hand, it seems to be fairly simple to create a new type that would store length of succeeding list with each element basing on F# List. You can implement it on Your own if You need it. Those, who don't need it will use standard implementation.
I don't often find myself needing to know the length of the list, it's not like you need it to exit a for loop like you would with arrays in imperative languages.
For those rare cases when you really need to know the length asap, you can go with Carsten König's suggestion from a comment and make your 'a list into a ('a * int) list, where each node keeps the length of the tail as a tuple element.
Then you can have something like this:
let push lst e =
match lst with
| (_, c)::_ -> (e, c + 1) :: lst
| [] -> [e, 0]
and length and pop functions to match.
For all the other cases I'd call it a premature optimization.

About lists:suffix/2 in Erlang

The source code:
suffix(Suffix, List) ->
Delta = length(List) - length(Suffix),
Delta >= 0 andalso nthtail(Delta, List) =:= Suffix.
How about rewriting it like the follow:
suffix(Suffix, List) ->
prefix(reverse(Suffix), reverse(List)).
If Delta >=0, the first one will traverse four times, and the second one will traverse three times, is it correct?
The first one (from stdlib lists.erl) will traverse both lists twice each, yes. On the other hand, on the second traversal all the list cells will probably be in L2 cache, and it doesn't have to allocate any data. Your suggestion works too, but has to build two reversed temporary lists on the heap, which both has a cost in allocating and initializing data structures as well as causing garbage collection to happen more often on average.
If you think about the same problem in C (or any similar language): testing whether one singly linked list is a suffix of another singly linked list, it becomes more obvious why it's hard to do efficiently, in particular if you want to avoid allocating memory, and you aren't allowed to use tricks like reversing pointers.
I don't think it is correct. As far as I know, length is a build in function which does not need to traverse the list to get the result (it is the reason why it is allowed in guard test), and the andalso is a kind of shortcut. if the first term is false, it does not evaluate the second term and directly return false.

How to create a loop using STL list in C++

This is an interview question: How to create a loop using the STL list container?
I am a newbie. I searched this question and did not find any. If this is an old question please give me the link and delete this post.
Thank you all!
How to create a loop using the STL list container?
You can't.
std::list has a beginning and an end. All access to the data structure is carefully controlled so that a standard-compliant program simply cannot produce a non-terminating list.
P.s. I'm assuming that the interviewer actually meant to say "std::list" instead of "STL list."
One possible answer is: It can happen when more than one thread is manipulating the list structure at the same time. Suppose two threads want to push_back into an already formed list. If the list already has b and a, the circular list could look like:
.--------------------------.
( )
`-> a <-> SENTINEL <-> b <-'
And one thread inserts c at the same time another inserts d. They each want to attach to the back of the SENTINEL like this:
a <-> c <-> SENTINEL
a <-> d <-> SENTINEL
However, the could end up making a loop:
.------------.
a. `-. )
`-> c <-> d <-'
<--> SENTINEL <-> b (<-> a)
The forward links are fine: b -> a -> c -> d
But the reverse links will loop: d -> c -> d ...
This can happen because the pointers of the SENTINEL is being read, dereferenced, and modified without mutual exclusion.