This article is my own thinking and analysis when reading the cracking the code interview 6th edition.
Chapter 2 Linked Lists
The basic singly linked list is of the following code:
public class Node {
Node next = null;
int data;
public Node(int d){
data = d;
}
void appendToTail(int d){
Node end = new Node(d);
Node n = this;
while (n.next != null){
n = n.next;
}
n.next = end;
}
}
Abstract:
This Chapter mainly discussed how to access a precise node in the linked list and how to trace the special node in a special structure, such as loop and intersection. It seems no difficulties in the chapter to understand. However, the most difficult thing in this chapter is recursion design. How to design a recursion, how do decompose the recursion structure to keep track the data among the nodes? More practice is required in recursion.
2.1 Write code to remove duplicates from an unsorted linked list.
Analysis:
There is no data base for this linked list, so a buffer to store scanned data is required. The basic thought now is to iterate through the list and check every element. Once the duplicate date was found, remove this node from this list.
Solution description:
iterate through the list and use Hash Set to store every scanned data. Use the way in chapter one to check duplicate data.
(comment: Because the language I use is Java which is different from the book. Here I just represent the code I wrote. All the code from the book will not be shown out.)
public LinkedList<E> ChapterTwo01(LinkedList<E> linklist) {
// TODO Auto-generated constructor stub
HashSet<E> buffer = new HashSet<E>();
int i = 0;
for( E data : linklist){
if(buffer.contains(data)){
linklist.remove(i);
}
else{
buffer.add(data);
}
i++;
}
return linklist;
}
FOLLOW UP:
How would you solve this problem if a temporary buffer is not allowed?
Analysis:
If there is no buffer to hold the data, the only thing we can do is to compare each data with the rest of the list. This solution wastes time but saves spaces.
Solution description:
Use loop within a loop to check the duplicate data.
public LinkedList<E> ChapterTwo01FollowUP(LinkedList<E> linklist){
for(int i = 0; i< linklist.size(); i++){
for(int j = i; j<linklist.size(); j++){
if(linklist.get(i) == linklist.get(j)){
linklist.remove(j);
}
}
}
return linklist;
}
What I got:
Save memory sometimes will cause a huge waste of processing time.
2.2 Implement an algorithm to find the kth to last element of a singly linked list.
Analysis:
Kth to last element is the Kth element that counts from the backwards to the front. Here the thing is worth to notice that singly linked list can only move forward.
If the length is known to us, then the answer is simple – just count the data position based on the length.
If the length is not known to us, we need to first get the length then count the Kth element from the end.
Solution description:
(1) Use counter to count the length while iterate through the list. Then calculate the position to get the data.
public int ChapterTwo02V1(Node listhead, int k) {
// TODO Auto-generated constructor stub
Node tracer = listhead;
int length = 0;
//count the length of the list
while(tracer.next != null){
length ++;
tracer = tracer.next;
}
//fetch the data
for(int i = 0; i< length - k; i++){
listhead = listhead.next;
}
return listhead.data;
}
(2) We could use the recursion to trace the data back.
public void ChapterTwo02V2(Node listhead, int k){
int i = 0;
recursion(listhead, k, i);
}
private int recursion(Node listhead, int k, int i) {
// TODO Auto-generated method stub
int length = 0;
if(listhead.next != null){
i++;
length = recursion(listhead.next, k, i);
if(length - i == k){
System.out.println(listhead.data);
}
}
else{
//the final element, now i is the length of this list
if(k == 0) System.