本博客目录
- 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 复制含有随机指针节点的链表
- 两个单链表相交的一系列问题
将单向链表按某值划分成左边小、中间相等、右边大的形式
给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数p。实现一个调整链表的函数,将链表调整为左部分都是值小于 p的节点,中间部分都是值等于p的节点,右部分都是值大于 p的节点。
空间复杂度为O(N)的算法
//建立辅助数组,先在数组上排序,之后连接 //空间复杂度O(n) ListNode* listPartition1(ListNode* head, int num) { if (head == NULL || head->next == NULL) { return head; } int i = 0; ListNode* cur = head; vector<ListNode*> arr; while (cur != NULL){ i++; arr.push_back(cur); cur = cur->next; } arrPartition(arr, num); for (i = 1; i != arr.size(); i++) { arr[i - 1]->next = arr[i]; } arr[i - 1]->next = NULL; return arr[0]; } void arrPartition(vector<ListNode*> arr, int num) { int length = arr.size(); int less = -1; int more = length; int cur = 0; while (cur >= more) { if (arr[cur]->val == num) { cur++; } else if (arr[cur]->val < num) { swap(arr, cur++, ++less); less++; } else { swap(arr, cur, --more); } } } void (vector<ListNode*> arr, int i, int j) { ListNode* tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
空间复杂度为O(1)的算法
//将链表分成三个部分: //分别为小于p、等于p、大于p //分别用一串链表连接起来,最终,连接成一个链表 ListNode* listPartition2(ListNode* head, int num) { ListNode* sH = NULL; ListNode* sT = NULL; ListNode* eH = NULL; ListNode* eT = NULL; ListNode* bH = NULL; ListNode* bT = NULL; ListNode* next = NULL; while (head != NULL) { next = head->next; head->next = NULL; if (head->val < num) { if (sH == NULL) { sT = head; sH == head; } else { sT->next = head; sT = head; } } else if (head->val > num) { if (bH == NULL) { bH = head; bT = head; } else { bT->next = head; bT = head; } } else{ if (eH == NULL) { eH = head; eT = head; } else { eT->next = head; eT = head; } } head = next; } if (sT != NULL) { sT->next = eH; eT = eT == NULL ? sT : eT; } if (eT != NULL) { eT->next = bH; } return sH != NULL ? sH : eH != NULL ? eH : bH; }
复制含有随机指针节点的链表
ListNode* copyListWithRand(ListNode* head) { if (head == NULL) { return NULL; } ListNode* cur = head; while (cur != NULL) { ListNode* node = new ListNode(cur->val); node->next = cur->next; cur->next = node; cur = node->next; } cur = head; while (cur != NULL) { ListNode* node = cur->next; node->random = cur->random == NULL ? NULL : cur->random->next; cur = node->next; } cur = head; ListNode* cloneHead = head->next; while (cur->next != NULL){ //注意边界处理,不然容易溢出 ListNode* node = cur->next; cur->next = node->next; cur = node; } return cloneHead; }
两个单链表相交的一系列问题
单链表可能有环,也可能无环。给定两个单链表的头节点 head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数, 如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null 即可。
/* 这个问题要考虑几种情况: 1. 两个链表都是单链表,判断入环节点 2. 两个链表都有环,判断入环节点 3. 一个链表有环,一个链表无环,则一定不想交。因为它们都是单链表。 */ ListNode* findFirst(ListNode* head1, ListNode* head2) { ListNode* loop1 = isLoop(head1); ListNode* loop2 = isLoop(head2); ListNode* firstNode = NULL; if (loop1 == NULL && loop2 == NULL) { firstNode = noLoop(head1, head2); } else if (loop1 != NULL && loop2 != NULL) { firstNode = bothLoop(head1, head2, loop1, loop2); } else { firstNode = NULL; } return firstNode; } //判断一个链表是否有环 //返回入环的节点 ListNode* isLoop(ListNode* head) { if (head == NULL || head->next == NULL || head->next->next == NULL) { return NULL; } ListNode* slow = head->next; ListNode* fast = head->next->next; while (slow != fast) { if (fast->next == NULL || fast->next->next == NULL) { return NULL; } slow = slow->next; fast = fast->next->next; } fast = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return slow; } //都无环的情况 ListNode* noLoop(ListNode* head1, ListNode* head2) { if (head1 == NULL || head2 == NULL) { return NULL; } int n = 0; ListNode* cur1 = head1; ListNode* cur2 = head2; while (cur1->next != NULL) { n++; cur1 = cur1->next; } while (cur2->next != NULL){ n--; cur2 = cur2->next; } if (cur1 != cur2) { return NULL; } cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = abs(n); while (n != 0) { n--; cur1 = cur1->next; } while (cur1 != cur2) { cur1 = cur1->next; cur2 = cur2->next; } return cur1; } //都有环的情况 ListNode* bothLoop(ListNode* head1, ListNode* head2, ListNode* loop1, ListNode* loop2) { ListNode* cur1 = NULL; ListNode* cur2 = NULL; if (loop1 == loop2) { int n = 0; cur1 = head1; cur2 = head2; while (cur1 != loop1) { n++; cur1 = cur1->next; } while (cur2 != loop2) { n--; cur2 = cur2->next; } cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = abs(n); while (n != 0){ n--; cur1 = cur1->next; } while (cur1 != cur2){ cur1 = cur1->next; cur2 = cur2->next; } return cur1; } else { cur1 = loop1->next; while (cur1 != loop1){ if (cur1 == loop2) { return loop1; } cur1 = cur1->next; } return NULL; } }
参考
牛客网左程云算法课