D
This is a solution I thought of myself. It runs in O(n) and uses O(1) memory.
What I'm doing is simply iterating through the list and reversing all the pointers. If the list contains a cycle, you'll eventually end up at the beginning of the list and otherwise you end up at the end, which is somewhere else if your list is longer than 1. Now you've determined the result you can restore the list by simply reversing the pointers again.
Here is my code and a test:
import std.stdio;
// The list structure.
struct node(T)
{
T data;
node!T * next;
this(T data) {this.data = data; next = null;}
}
bool hasLoop(T)(node!T * first)
{
// List shorter than two nodes has no loops.
if(!first || !first.next)
{
return false;
}
// Keep iterating through the list, while reversing the pointers.
node!T * previous = null,
current = first;
while(current)
{
auto next = current.next;
current.next = previous;
previous = current;
current = next;
}
// If the last node was the beginning of the list, there was a cycle.
// Otherwise, there are none.
bool result = previous == first;
// Do the reversal again to restore the list to its original state.
current = previous;
previous = null;
while(current)
{
auto next = current.next;
current.next = previous;
previous = current;
current = next;
}
// Done!
return result;
}
// Test
unittest
{
// Build a list.
int[] elems = [1,2,3,4,5,6,7,8,42];
auto list = new node!int(elems[0]);
auto curr = list;
foreach(x; elems[1..$])
{
curr.next = new node!int(x);
curr = curr.next;
}
// Outcomment the line below to test for a non-cycle list.
curr.next = list.next.next.next;
// Do cycle check.
writeln(hasLoop(list) ? "yes" : "no");
// Confirm the list is still correct.
curr = list;
for(int i = 0; i < elems.length; ++i, curr = curr.next)
{
assert(curr.data == elems[i]);
}
}
f:int->int
. Givenf
andx0
, letF(x) = if x=0 then 0 else f(x)
. Is there an intn
such thatf^n(x0) = 0
? \$\endgroup\$F^n(x0) = 0
\$\endgroup\$f
suggests that it is a total function when it isn't. For example, it isn't correct to callf
on any value that isn't of the formf^k(x0)
for somek
. Think about it like a monad if you want to apply it more generally, not as a function whose domain is integers. \$\endgroup\$