1. 求单链表中节点的个数
2. 将单链表反转
3. 查找单链表中的倒数第K个节点(k > 0)
4. 查找单链表的中间节点
5. 从尾到头打印单链表
6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
7. 判断一个单链表中是否有环
8. 判断两个单链表是否相交
9. 求两个单链表相交的第一个节点
10. 已知一个单链表中存在环,求进入环中的第一个节点
11. 删除单向链表中间的某个节点,假定你只能访问该节点
12. 检查链表是否为回文
13. 移除未排序链表中的重复节点
14. 给定两个用链表表示的整数,每个节点包含一个数位,这些数位是方向存放的,对这两个整数求和,并用链表形式返回结果
链表节点定义:
typedef struct ListNode {
int value;
struct ListNode *next;
}ListNode;
1. 求单链表中结点的个数
int getListLength(ListNode *head) {
if (head == NULL)
return 0;
ListNode *p = head;
int count = 0;
while (p) {
count++;
p = p->next;
}
return count;
}
2. 将单链表反转
ListNode* reverseList(ListNode *head) {
if (head == NULL)
return head;
ListNode *rHead = NULL;
ListNode *p = head;
while (p) {
ListNode *t = p;
p = p->next;
t->next = rHead;
rHead = t;
}
return rHead;
}
3. 查找单链表中的倒数第K个结点(k > 0)
ListNode* getKthNodeFromEnd(ListNode *head, int k)
{
if (head == NULL || k <= 0)
return head;
ListNode *slow = head;
ListNode *fast = head;
while (k > 0 && fast != NULL) {
fast = fast->next;
k--;
}
if (k > 0)
return NULL;
if (fast == NULL) {
return slow;
}
while (fast->next) {
slow = slow->next;
fast = fast->next;
}
return slow->next;
}
4. 查找单链表的中间结点
ListNode* getMidNode(ListNode *head) {
ListNode *slow = head;
ListNode *fast = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
5. 从尾到头打印单链表
void reversePlayList(ListNode *head) {
if (head == NULL)
return;
PrintListFromEnd(head->next);
printf("%d ", head->value);
}
6. 已知两个单链表head1和head2各自有序,把它们合并成一个链表依然有序
ListNode* mergeLists(ListNode *head1, ListNode *head2) {
ListNode *head = NULL;
ListNode *p = NULL;
ListNode *t;
while (head1 && head2) {
if (head1->value < head2->value) {
if (head == NULL) {
head = p = head1;
}
t = head1;
head1 = head1->next;
} else {
if (head == NULL) {
head = p = head2;
}
t = head2;
head2 = head2->next;
}
p->next = t;
p = t;
}
if (head1 == NULL)
p->next = head2;
if (head2 == NULL)
p->next = head1;
return head;
}
7. 判断一个单链表中是否有环
bool hasCircle(ListNode *head) {
ListNode *slow = head;
ListNode *fast = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) //有环快慢指针必相遇
return true;
}
return false;
}
8. 判断两个单链表是否相交
bool isIntersect(ListNode *head1, ListNode *head2) {
if (head1 == NULL || head2 == NULL)
return false;
while (head1->next)
head1 = head1->next;
while (head2->next)
head2 = head2->next;
return head1 == head2; //若相交,最后一个节点必为两者所有
}
9. 求两个单链表相交的第一个节点
ListNode* getFirstCommonNode(ListNode *head1, ListNode *head2) {
if (head1 == NULL || head2 == NULL)
return NULL;
int len1 = 0, len2 = 0;
ListNode *p1 = head1;
ListNode *p2 = head2;
while (p1) {
len1++;
p1 = p1->next;
}
while (p2) {
len2++;
p2 = p2->next;
}
if (p1 != p2)
return NULL;
p1 = head1;
p2 = head2;
if (len1 > len2) {
int k = len1 - len2;
while (k--)
p1 = p1->next;
} else {
int k = len2 - len1;
while (k--)
p2 = p2->next;
}
while (p1 != p2) {
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
10. 已知一个单链表中存在环,求进入环中的第一个节点
从环中相遇的节点,把链表分开,转成求两链表的相交的第一个节点
ListNode* getFirstNodeInCircle(ListNode *head) {
if (head == NULL || head->next == NULL)
return NULL;
ListNode *fast = head;
ListNode *slow = head;
while (fast->next->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
break;
}
if (fast != slow)
return NULL;
ListNode *p1 = head;
ListNode *p2 = fast->next;
int len1 = 1;
int len2 = 1;
while (p1 != slow) {
p1 = p1->next;
len1++;
}
while (p2 != slow) {
p2 = p2->next;
len2++;
}
p1 = head;
p2 = fast->next;
if (len1 > len2) {
int k = len1 - len2;
while (k--)
p1 = p1->next;
} else {
int k = len2 - len1;
while (k--)
p2 = p2->next;
}
while(p1 != p2) {
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
11. 删除单向链表中间的某个节点,假定你只能访问该节点
用下一个节点覆盖该节点,当该节点为尾节点时,无法操作
bool deleteNode(ListNode *node) {
if (node == NULL || node->next == NULL)
return false;
ListNode *p = node->next;
node->value = p->value;
node->next = p->next;
delete p;
return true;
}
12. 检查链表是否为回文
反转链表,然后和原链表比较
13. 移除未排序链表中的重复节点
void deleteDups(ListNode *head) {
if (head == NULL || head->next == NULL)
return;
map<int, ListNode *> listMap;
ListNode *p = head;
ListNode *temp;
listMap[p->value] = p;
while (p->next) {
if (listMap.find(p->next->value)) {
temp = p->next;
p->next = p->next->next;
delete temp;
} else {
listMap[p->next->value] = p->next;
}
p = p->next;
}
}
14. 给定两个用链表表示的整数,每个节点包含一个数位,这些数位是方向存放的,对这两个整数求和,并用链表形式返回结果
ListNode* addTwoNumbers(ListNode *head1, ListNode *head2) {
ListNode *header = new ListNode(-1);
ListNode *result = header;
int val = 0;
int extra = 0;
while (head1 || head2) {
val = (head1 != NULL ? head1->value : 0) + (head2 != NULL ? head2->value : 0) + extra;
extra = val / 10;
val %= 10;
ListNode *node = new ListNode(val);
node->value = val;
result->next = node;
result = result->next;
if (head1) {
head1 = head1->next;
}
if (head2) {
head2 = head2->next;
}
}
if (extra > 0) {
ListNode *node = new ListNode(extra);
result->next = node;
}
result = header->next;
delete header;
return result;
}