目录
相交链表
反转链表
回文链表
环形链表
合并两个有序链表
相交链表
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if (headA == nullptr || headB == nullptr) {return nullptr;}ListNode *pA = headA;ListNode *pB = headB;while (pA != pB) {pA = (pA == nullptr)? headB : pA->next;pB = (pB == nullptr)? headA : pB->next;}return pA;}
显然while循环是整个逻辑最重要的地方:这里使用了双指针的方法。
- 外层循环:
while (pA != pB)
表示只要指针pA
和pB
没有指向同一个节点,就持续循环。这是确保两个指针不断移动,直到找到相交节点或者确定没有相交节点的控制条件。 pA
指针移动逻辑:pA = (pA == nullptr)? headB : pA->next;
这行代码使用了条件运算符(三元运算符)。如果pA
指向nullptr
,意味着pA
已经遍历完了它原本所在的链表,此时将pA
重新指向链表headB
的头节点;否则,pA
就移动到当前节点的下一个节点。pB
指针移动逻辑:pB = (pB == nullptr)? headA : pB->next;
与pA
的移动逻辑类似。如果pB
指向nullptr
,即pB
遍历完了它原本所在的链表,就将pB
重新指向链表headA
的头节点;否则,pB
移动到当前节点的下一个节点。
通过这样的逻辑,两个指针会在相同的总步数下遍历链表。如果两个链表相交,它们最终会指向同一个相交节点;如果两个链表不相交,那么 pA
和 pB
最终都会指向 nullptr
,从而结束循环。
例如,假设有两个链表 A
和 B
,A
链表为 1 -> 2 -> 3 -> 6 -> 7
,B
链表为 4 -> 5 -> 6 -> 7
,pA
从 A
链表头 1
开始,pB
从 B
链表头 4
开始。当 pA
遍历完 1 -> 2 -> 3
后指向 nullptr
,此时重新指向 B
链表头 4
,继续遍历 4 -> 5
,而 pB
遍历完 4 -> 5
后指向 nullptr
,重新指向 A
链表头 1
,继续遍历 1 -> 2 -> 3
,最终 pA
和 pB
都会指向相交节点 6
。
反转链表
ListNode* reverseList(ListNode* head) {// 递归终止条件:如果当前节点为空或为尾节点,直接返回if (head == nullptr || head->next == nullptr) {return head;}// 递归处理当前节点的下一个节点ListNode* newHead = reverseList(head->next);// 回溯部分:反转指针方向head->next->next = head;head->next = nullptr;return newHead;}
- 递归法:以节点为单位进行操作,从链表尾部开始反转。函数接收当前节点作为参数,先递归调用自身处理当前节点的下一个节点,当到达链表尾部时返回该节点(作为新的头节点)。然后在回溯过程中,将当前节点的下一个节点的
next
指针指向当前节点,并将当前节点的next
指针置空,完成反转操作。
回文链表
bool isPalindrome(ListNode* head) {bool b=true;std::vector<int> temp;ListNode* p=head;while(p!=nullptr){temp.push_back(p->val);p = p->next;}int n = temp.size();for (int i = 0; i < n / 2; ++i) {if (temp[i] != temp[n - 1 - i]) {return false;}}return b;}
好吧,通过很笨的办法,把链表弄到数组里,然后两个指针依次比较q_q
环形链表
bool hasCycle(ListNode *head) {std::unordered_set<ListNode*> visited;ListNode* curr = head;while (curr != nullptr) {// 如果节点已在哈希表中,说明有环if (visited.find(curr) != visited.end()) {return true;}// 将当前节点加入哈希表visited.insert(curr);// 移动到下一个节点curr = curr->next;}// 遍历完链表无重复,说明无环return false;}
好吧,依旧是简单粗暴,直接丢哈希表里面,然后通过哈希表现有的函数直接去检查是否冲突
合并两个有序链表
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {ListNode* dummy=new ListNode();ListNode* curr=dummy;ListNode* p1=list1;ListNode* p2=list2;while(p1!=nullptr&&p2!=nullptr){if(p1->val<p2->val){curr->next=p1;p1=p1->next;}else{curr->next=p2;p2=p2->next;}curr=curr->next;}curr->next=(p1!=nullptr)?p1:p2;ListNode* result=dummy->next;delete dummy;return result;}
这里使用了迭代法,依旧是简单无脑遍历,通过两个指针比大小,小的就先放进去。嗯就这样。