# LinkListDemo
**Repository Path**: thunderHou/LinkListDemo
## Basic Information
- **Project Name**: LinkListDemo
- **Description**: 链表算法练习
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-05-21
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 链表算法练习
### 本文包含链表的以下内容:
1. 单链表的创建和遍历
2. 求单链表中节点的个数
3. 查找单链表中的倒数第k个结点(剑指offer,题15)
4. 查找单链表中的中间结点
5. 合并两个有序的单链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)
6. 单链表的反转【出现频率最高】(剑指offer,题16)
7. 从尾到头打印单链表(剑指offer,题5)
8. 判断单链表是否有环
9. 取出有环链表中,环的长度
10. 单链表中,取出环的起始点(剑指offer,题56)。本题需利用上面的第8题和第9题。
11. 判断两个单链表相交的第一个交点(剑指offer,题37)
### 代码部分
- 5、合并两个有序的单链表,合并之后的链表依然有序:(这道题经常被各公司考察)
```
例如:
链表1:1->2->3->4
链表2:2->3->4->5
合并后:1->2->2->3->3->4->4->5
解题思路:
挨着比较链表1和链表2。
这个类似于归并排序。尤其要注意两个链表都为空、和其中一个为空的情况。只需要O(1)的空间。时间复杂度为O(max(len1,len2))
代码实现:
//两个参数代表的是两个链表的头结点
public Node mergeLinkList(Node head1, Node head2) {
if (head1 == null && head2 == null) { //如果两个链表都为空
return null;
}
if (head1 == null) {
return head2;
}
if (head2 == null) {
return head1;
}
Node head; //新链表的头结点
Node current; //current结点指向新链表
// 一开始,我们让current结点指向head1和head2中较小的数据,得到head结点
if (head1.data < head2.data) {
head = head1;
current = head1;
head1 = head1.next;
} else {
head = head2;
current = head2;
head2 = head2.next;
}
while (head1 != null && head2 != null) {
if (head1.data < head2.data) {
current.next = head1; //新链表中,current指针的下一个结点对应较小的那个数据
current = current.next; //current指针下移
head1 = head1.next;
} else {
current.next = head2;
current = current.next;
head2 = head2.next;
}
}
//合并剩余的元素
if (head1 != null) { //说明链表2遍历完了,是空的
current.next = head1;
}
if (head2 != null) { //说明链表1遍历完了,是空的
current.next = head2;
}
return head;
}
```
- 6、单链表的反转:【出现频率最高】
```
例如链表:1->2->3->4
反转之后:4->3->2->1
思路:从头到尾遍历原链表,每遍历一个结点,将其摘下放在新链表的最前端。注意链表为空和只有一个结点的情况。时间复杂度为O(n)
代码实现:
public Node reverseList(Node head) {
//如果链表为空或者只有一个节点,无需反转,直接返回原链表的头结点
if (head == null || head.next == null) {
return head;
}
Node current = head;
Node next = null; //定义当前结点的下一个结点
Node reverseHead = null; //反转后新链表的表头
while (current != null) {
next = current.next; //暂时保存住当前结点的下一个结点,因为下一次要用
current.next = reverseHead; //将current的下一个结点指向新链表的头结点
reverseHead = current;
current = next; // 操作结束后,current节点后移
}
return reverseHead;
}
```
### 鸣谢
- [链表面试题Java实现](https://www.cnblogs.com/smyhvae/p/4782595.html)