The two pointers can also have the same speed and different starts. To find the k-th node from the end, send one of them k steps ahead first, then walk both together. When the one in front reaches the end, the one behind is exactly k steps back, on the node you want.
lead = headfor _ in range(k):lead = lead.nexttrail = headwhile lead is not None:lead = lead.nexttrail = trail.nextreturn trail
With different speeds you learn something else: does the chain have a cycle? If it has none the fast pointer reaches the end and it is over. If it has one, the fast pointer goes round and round inside and catches the slow one up from behind: the two meet on the same node. There is no need to keep the nodes seen in a set.