1.链表反转
//递归
ListNode *reverseList(ListNode *head){
if(!head || !head->next) return head;
ListNode *node = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return node;
}
//三个指针
void reverseList(ListNode *head){
if(head == NULL || head->next == NULL) return;
ListNode *pre = NULL, *cur = head, *next = NULL;
while(current != NULL){
next = cur ->next;
cur->next = pre;
pre = cur;
cur = next;
}
}
2.倒序输出链表
//复杂度O(n)
void recursivePrint(ListNode* node){
if(node == NULL) return;
if(node->next){
recursivePrint(node->next);
}
printf("%d",node->value);
}
3.输出链表中倒数第 k 个节点,k从1开始计数。
ListNode *getKNode(ListNode *head, int k){
if (!head) return NULL;
ListNode *fast = head;
ListNode *slow = head;
for(int i = 0 ; i < k ; i++){
fast = fast->next;
}
while(fast != NULL){
fast = fast->next;
slow = slow->next;
}
return slow;
}
4.删除单链表指定节点
//复杂度是O(1)
void deleateNode(ListNode * head, ListNode*deleteNode){
if(!deleteNode) return;
if(deleteNode->next){
//不是尾节点
ListNode *temp = deleteNode->next;
deleteNode->next = temp->next;
deleteNode->value = temp->value;
}else if (head == deleteNode){
//删除的是首节点
head = NULL;
deleteNode = NULL;
}else{
//删除尾结点
ListNode *temp = head;
while (temp->next != deleteNode){
temp = temp->next;
}
temp->next = NULL;
deleteNode = NULL;
}
}
//复杂度是O(n)
void deleateNode(ListNode * head, ListNode*deleteNode){
if(!deleteNode) return;
ListNode *p = head;
while(p->next != deleteNode){
p = p ->next;
}
p->next = deleteNode->next;
}
5.查找中间结点
ListNode *middle(ListNode * head){
ListNode *fast = head, *slow = head
while(fast->next != NULL && fast != NULL){
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
6.判断一个链表是否有环
//复杂度O(n)
int haveRing(ListNode *head){
ListNode *fast = head, *slow = head
while( fast != NULL && fast->next != NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
return 1;
}
}
return 0;
}
7.找出链表中环的入口结点
链表头到环入口的距离是a,
环入口到相遇点的距离是b,
相遇点到环入口的距离是c,
我们可知快指针走过的路程是 x = a + k * (b+c) + b k为走过的圈数,大于等于1
慢指针走过的路程是y = a + b;
快指针走过路程的是满指针的两倍可得: x = 2y; a = (k-1)(b + c) + c = a ;
所以链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈数环长度。其中k>=1,所以k-1>=0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
//复杂度O(n)
ListNode *findEntry(ListNode *head){
ListNode *fast = head, *slow = head
while(fast->next != NULL && fast != NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
break;
}
}
if(fast == NULL){
//没有环
return NULL;
}
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
8.判断两个链表是否相交
//复杂度O(n+m)
int isIntersect(ListNode * head1, ListNode * head2){
if(a == NULL || b == NULL) return 0;
ListNode *p = head1, *q = head2
while(p->next != NULL){
p = p->next;
}
while(q->next != NULL){
q = q->next;
}
return p == q ? 1 : 0;
}
9.找两个相交的链表的交点
ListNode *getIntersectionNode(ListNode *head1, ListNode * head2){
if(a == NULL || b == NULL) return NULL;
int len1 = 0, len2 = 0, diff = 0;
ListNode *p = head1, *q = head2;
while(p->next != NULL){
p = p->next;
len1++;
}
while(q->next != NULL){
q = q->next;
len2++;
}
if(p != q) return NULL;
diff = abs(len1- len2);
if(len1 > len2){
p = head1;
q = head2;
}else{
q = head1;
p = head2;
}
for(int i = 0 ; i < diff ; i++){
p = p->next;
}
while(p = q){
p = p->next;
q = q->next;
}
return p;
}
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == NULL || headB == NULL) {
return NULL;
}
ListNode *p = headA, *q = headB;
while(p != q){
p=p==NULL?headB:p->next;
q=q==NULL?headA:q->next;
}
return p;
}
10.给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
void reorderList(ListNode* head){
if (head == NULL || head->next == NULL || head->next->next == NULL) return ;
ListNode *fast = head, *slow = head, *newHead;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
slow = slow->next;
}
newHead = slow->next;
slow->next = NULL;
ListNode *pre = NULL, *nex1;
while(newHead != NULL){
nex1 = newHead->next;
newHead->next = pre;
pre = newHead;
newHead = nex1;
}
newHead = pre;
while(newHead != NULL && head != NULL){
nex1 = newHead->next;
newHead->next = head->next;
head->next = newHead;
head = newHead->next;
newHead = nex1;
}
return ;
}
11.分隔链表
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。你应当保留两个分区中每个节点的初始相对位置。比如:
输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
ListNode* partition(ListNode* head, int x){
if(!head) return NULL;
ListNode less_head;
ListNode more_head;
less_head.val = 0;
less_head.next= NULL;
more_head.val = 0;
more_head.next= NULL;
ListNode *before = &less_head;
ListNode *after = &more_head;
while(head){
if(head->val < x){
before->next = head;
before = head;
}else{
after->next = head;
after = head;
}
head = head->next;
}
before->next = more_head.next;
after->next = NULL;
return less_head.next;
}
11.链表是否有环,如果有,返回入环节点,没有返回NULL
ListNode *detectCycle(ListNode *head) {
if(!head) return NULL;
ListNode *fast = head;
ListNode *slow = head;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
}
return NULL;
}