目录
一 链表的回文结构
原题链接:
链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
⭐:回文结构也就是对称结构,即一串结构正着读和反着读一模一样。
例如:1 2 2 1 或者 1 2 3 2 1
思路:
先找到链表的中间结点,然后再对链表中间结点往后的结点进行逆置。逆置后与中间结点前面的结点进行比较。(求链表中间结点和链表逆置在上篇博客已经讲过,这里不再过多赘述.)
注:因为C++包容C,所以题解用的C语言写的。
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) {} };*/ class PalindromeList { public: //求链表的中间结点 struct ListNode* middleNode(struct ListNode* head) { struct ListNode* slow, * fast; slow = fast = head; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; } return slow; } //反转链表 struct ListNode* reverseList(struct ListNode* head) { struct ListNode* newHead = NULL; struct ListNode* cur = head; while (cur) { struct ListNode* next = cur->next; //头插 cur->next = newHead; newHead = cur; cur = next; } return newHead; } bool chkPalindrome(ListNode* A) { struct ListNode*mid=middleNode(A); struct ListNode*rHead=reverseList(mid); while(A && rHead) { if(A->val == rHead->val) { A = A->next; rHead = rHead->next; } else { return false; } } return true; } };
二 链表的相交
原题链接:
160. 相交链表 - 力扣(LeetCode) (leetcode-cn.com)
思路1:
A链表的每个结点跟B链表依次比较,如果有相等,就是相交,第一个相等的结点就是交点。此种方法的时间复杂度为O(M*N).
思路2:
对比A链表和B链表的尾结点,如果两个链表的尾结点地址相同,则链表就是相交。然后我们可以求出两个链表的长度La和Lb,让长的先走|La-Lb|步,再一起走,第一个地址相等的结点就是相交点。此种方法的时间复杂度为O(M+N).
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) { struct ListNode* tailA = headA, * tailB = headB; int lenA=1, lenB=1;//因为后面找链表的尾结点会少算一个,所以将它们都初始化为1 //找链表的尾结点 while (tailA->next) { tailA = tailA->next; lenA++; } while (tailB->next) { tailB = tailB->next; lenB++; } //如果尾结点不相同,则说明两个链表不相交,返回空指针 if (tailA != tailB) { return NULL; } //相交,求交点,长的先走差距步,再同时走找交点。 struct ListNode* shortList = headA, * longList = headB; if (lenA > lenB) { longList = headA; shortList = headB; } //求出差距步 int gap = abs(lenA - lenB); while (gap--) { longList = longList->next; } //求相交结点 while (shortList && longList) { if (shortList == longList) { return shortList; } shortList = shortList->next; longList = longList->next; } //按照语法逻辑,这里仍需要写返回值,要不然会报语法错误即编译出错 return NULL; }
三 复制带随机指针的链表(较难)
原题链接:
这道题的题目看起来挺吓人的,现在让我们慢慢的分析一下。
法一:
题目要求我们拷贝一个新的链表,那么我们可以malloc出一个新的链表。我们创建一个指针 变量cur依次遍历链表,比如cur遍历到第一个结点,那么我们就malloc出一个和第一个结点数据相同的结点。然后再遍历再malloc,继续尾插,直到结束。对于random指针,我们可以用找相对距离的方法,原链表的random指向第几个,新链表的random也指向第几个。此方法时间复杂度为O(N^2).
法二:
首先我们把所需要拷贝的结点连接在原结点的后面
struct Node* cur = head; //拷贝节点链接在原节点后面 while (cur) { struct Node* copy = (struct Node*)malloc(sizeof(struct Node)); copy->val = cur->val; copy->next = cur->next; cur->next = copy; cur = cur->next->next; }
然后通过原结点找到所对应的random
比如我们所拷贝出来的数据为13的结点,拷贝出来的结点就是原来数据为13的结点的next。因为在原链表中13的random指向7,所以在我们拷贝出来的13的random也要指向拷贝出来的7,而在原链表中7的next指向拷贝出的7。所以拷贝出来的13的random就是原来的13的random的next。其他结点类推。
//更新拷贝节点的random cur = head; while (cur) { struct Node* copy = cur->next; if (cur->random == NULL) { copy->random = NULL; } else { copy->random = cur->random->next; } cur = cur->next->next; }
恢复原链表,把拷贝的链表连接在一起。
//拷贝节点与原结点分离,连接在一起 cur = head; struct Node* copyTail = NULL; struct Node* copyHead = NULL; while (cur) { struct Node* copy = cur->next; struct Node* next = copy->next; cur->next = next; if (copyTail == NULL) { copyHead = copyTail = copy; } else { copyTail->next = copy; copyTail = copyTail->next; } cur = next; } return copyHead; }
总代码:
struct Node* copyRandomList(struct Node* head) { struct Node* cur = head; //拷贝节点链接在原节点后面 while (cur) { struct Node* copy = (struct Node*)malloc(sizeof(struct Node)); copy->val = cur->val; copy->next = cur->next; cur->next = copy; cur = cur->next->next; } //更新拷贝节点的random cur = head; while (cur) { struct Node* copy = cur->next; if (cur->random == NULL) { copy->random = NULL; } else { copy->random = cur->random->next; } cur = cur->next->next; } //拷贝结点与原结点分离,连接到一起 cur = head; struct Node* copyTail = NULL; struct Node* copyHead = NULL; while (cur) { struct Node* copy = cur->next; struct Node* next = copy->next; cur->next = next; if (copyTail == NULL) { copyHead = copyTail = copy; } else { copyTail->next = copy; copyTail = copyTail->next; } cur = next; } return copyHead; }
勿忘点赞噢~