# 面试算法之链表操作集锦

template <typename Type>
struct ListNode{
Type data;
ListNode *next;
};

/**
* Create a list, without head node
*/
template <typename Type>
ListNode<Type> *CreatList(Type *data, int len)
{
if(data == NULL || len <= 0)
return NULL;

for (int i = 0; i < len; ++i)
{
last->next = new ListNode<Type>;
last->next->data = data[i];
last = last->next;
}

last->next = NULL;

delete last;

}

### 1.单链表的逆序打印

/**
* reversely print the list
* method 1: use the stack
*/
template <typename Type>
{
return;

stack<Type> nodeStack;
{
}

while(!nodeStack.empty())
{
cout<<nodeStack.top()<<" ";
nodeStack.pop();
}
cout<<endl;
}


/**
* reversely print the list
* method 2: recursively
*/
template <typename Type>
{
return;

}

### 2.单链表的逆置

/**
* reverse the list
* method 1:sequential scanning
*/
template <typename Type>
{
return NULL;

ListNode<Type> *pre = NULL;

{
}

return pre;
}

/**
* reverse the list
* method 2: recursion
*/
template <typename Type>
{
return NULL;

}

template <typename Type>
{
{
}

}

### 3.在O(1)时间删除链表节点

/**
* delete a node from list
*/
template <typename Type>
ListNode<Type> * DeleteNode(ListNode<Type> *head, ListNode<Type> *node)
{
if(head == NULL || node == NULL)

//only have one node
if (node == head && node->next == NULL)
{
return NULL;
}

//node counts > 1, and delete the tail node
if (node->next == NULL)
{

while (pre->next != node)
pre = pre->next;

delete node;
pre->next = NULL;

}

//other node
ListNode<Type> *delNode = node->next;
node->data = delNode->data;
node->next = delNode->next;

delete delNode;

}

### 4.链表中的倒数第k个节点

• 遍历一遍节点统计链表的长度，然后计算出倒数第k个节点在链表中顺序的位置。
• 可以通过stack来保存链表顺序扫描的节点，然后弹出第k个节点。
• 可以通过递归来实现。

/**
* return the last k node from list, 1 =< k <= list length
*/
template <typename Type>
const ListNode<Type> * LastKNode(const ListNode<Type> *head, int k)
{
if(head == NULL || k < 1)
return NULL;

for (int i = 0; i < k - 1; ++i)
{
//the list length less than k
return NULL;

}

{
after = after->next;
}

return after;
}

### 5.合并两个排序的链表

/**
* merge two sorted list
*/
template <typename Type>
ListNode<Type> * MergeTwoSortedList(ListNode<Type> *H1, ListNode<Type> *H2)
{
if (H1 == NULL)
return H2;
if (H2 == NULL)
return H1;

while (H1 != NULL && H2 != NULL)
{
if (H1->data <= H2->data)
{
last->next = H1;
last = H1;
H1 = H1->next;
}
else
{
last->next = H2;
last = H2;
H2 = H2->next;
}
}

if (H1 != NULL)
last->next = H1;
else if (H2 != NULL)
last->next = H2;

return H1;
}


### 6.求两个单链表的第一个公共结点

• 最暴力的解法就是从一个链表的开头，把每个结点依次与另一个链表的所有结点进行依次比较，直到找到第一个公共结点为止，这种解法那叫一个暴力，时间复杂度为O(n^2)，面试官肯定会鄙视的。
• 采用stack辅助空间，分别将两个链表的各个结点依次入两个栈中，然后从两个栈中弹出结点，直到结点的内容不同为止，上一个结点就是所求。这种做法需要O(n)的辅助空间，估计也不是面试官最想要的。
• 采用对齐的方法。计算两个链表的长度l1,l2，分别用两个指针p1,p2指向两个链表的头，然后将较长链表的p1(假设为p1)向后移动l2 - l1个结点，然后再同时向后移动p1,p2，直到p1 = p2。这种方法才是面试官最想要的，具体代码实现如下：

/**
* Find the first common node
*/
template <typename Type>
ListNode<Type> * Find1stCommonNode(ListNode<Type> *h1, ListNode<Type> *h2)
{
if(h1 == NULL || h2 == NULL)
return NULL;

int len1, len2;

len1 = GetListLength(h1);
len2 = GetListLength(h2);

if (len1 > len2)
{
for (int i = 0;i < len1 - len2; ++i)
h1 = h1->next;
}
else
{
for (int i = 0;i < len2 - len1; ++i)
h2 = h2->next;
}

while (h1 && h1 != h2)
{
h1 = h1->next;
h2 = h2->next;
}

return h1;
}

template <typename Type>
{
int num = 0;

{
++num;
}

return num;
}

### 7.判断两个单链表是否相交

/**
* judge two list crossing or not
*/
template <typename Type>
bool IsCrossing(ListNode<Type> *h1, ListNode<Type> *h2)
{
if(h1 == NULL || h2 == NULL)
return false;

while(h1->next != NULL)
h1 = h1->next;
while(h2->next != NULL)
h2 = h2->next;

if(h1 == h2)
return true;
return false;
}

### 8.判断单链表是否存在环

/**
* judge the list has circle or not
*/
template <typename Type>
{
return false;

ListNode<Type> *fast, *slow;

while (fast && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;

if(fast == slow)
return true;
}

return false;
}

### 9.求链表的中间结点

/**
* get the middle node of list
*/
template <typename Type>
const ListNode<Type> * ListMidNode(const ListNode<Type> *head)
{
return NULL;

const ListNode<Type> *fast, *slow;

while(fast && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}

return slow;
}

while(fast && fast->next != NULL && fast->next->next != NULL)

Date: Sept 4rd, 2013 @lab