/*问题1
* 将链表的后半截逆序,然后跟前半截交叉生成新的链表。
* 要求: Time: O(N), Space: O(1),不允许递归如:1->2->3->4->5 ==>1->5->2->4->3
*/
void reserve(ListNode* &head) {
if (!head) return;
// 1->2->3->4->5
// 1 2 3 4 null
// s f
if (!head->next) {
return;
}
ListNode* slow = head;
ListNode* fast = head;
while (slow->next && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// 把 slow(不包含)后面的倒序
ListNode *r_list = nullptr;
ListNode* node = nullptr;
while (slow->next) { // 5 --> 4
if (!r_list) {
r_list = slow->next;
}
else {// 头插
node = slow->next;
node->next = r_list;
r_list = node;
}
slow->next = slow->next->next;
}
// 1->2->3 5->4 交叉合并
ListNode* new_list = nullptr;
ListNode* tail = nullptr;
ListNode* node1 = nullptr;
ListNode* node2 = nullptr;
while (head && r_list) {
node1 = head;
head = head->next;
node1->next = NULL;
node2 = r_list;
r_list = r_list->next;
node2->next = NULL;
// 尾插法
if (!new_list) {
new_list = node1;
new_list->next = node2;
tail = new_list->next;
}
else {
tail->next = node1;
tail = tail->next;
tail->next = node2;
tail = tail->next;
}
}
if (head) {
if(tail) tail->next = head;
}
head = new_list;
}
/*问题2
反转链表的[n,m]区间
*/
void head_insert(ListNode*& head, ListNode* node) {
if (!head) {
head = node;
}
else {
node->next = head;
head = node;
}
}
void reserve_n2m(ListNode* head, int n, int m) {
if (!head || n >= m || n < 0) return;
int dist = m - n;
// 找到第n个节点 并记录它前面一个节点
ListNode* pre_node = new ListNode(0);
pre_node->next = head;
ListNode* ptr = head; // 遍历节点
for (int i = 0; i < n; ++i) {
pre_node = ptr;
ptr = ptr->next;
}
ListNode* reserve_list = nullptr;
ListNode* node = nullptr;
// 把节点从原来的链表节点删除放入reserve_list中
for (int i = 0; i <= dist && pre_node->next; ++i) {
node = pre_node->next;
pre_node->next = pre_node->next->next;
node->next = nullptr;
head_insert(reserve_list, node);
}
// 在插入就行
node = pre_node->next;
ptr = reserve_list;
while (ptr->next) {
ptr = ptr->next;
}
pre_node->next = reserve_list;
ptr->next = node;
}
/*问题3
单链表快速排序
*/
ListNode* patition(ListNode* start, ListNode* end) {
ListNode* mid = start;
ListNode* tail = start->next;
int base = start->val;
while (tail != end) {
if (base > tail->val) {
mid = mid->next;
swap(mid->val, tail->val);
}
tail = tail->next;
}
swap(mid->val, start->val);
return mid;
}
void list_quick_sort(ListNode* start, ListNode* end) {
if (start != end && start->next != end) {
ListNode* mid = patition(start, end);
list_quick_sort(start, mid);
list_quick_sort(mid->next, end);
}
}
/*问题4
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。
(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围: n≤1000
要求:空间复杂度 O(1),时间复杂度 O(n)
*/
struct ListNode {
int val;
struct ListNode* next;
ListNode(int x) :
val(x), next(NULL) {
}
};
ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {
if (!pHead1 || !pHead2) return NULL;
ListNode* ptr1 = pHead1;
ListNode* ptr2 = pHead2;
uint16_t len1 = 0;
uint16_t len2 = 0;
while (ptr1) {
len1++;
ptr1 = ptr1->next;
}
while (ptr2) {
len2++;
ptr2 = ptr2->next;
}
ptr1 = pHead1;
ptr2 = pHead2;
if (len1 > len2) {// ptr1 长
for (int i = 0; i < len1 - len2; ++i) ptr1 = ptr1->next;
}
else {
for (int i = 0; i < len2 - len1; ++i) ptr2 = ptr2->next;
}
while (ptr1 && ptr2) {
if (ptr1 == ptr2) break;
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
if (!ptr2) return NULL;
return ptr2;
}
链表类题目
最新推荐文章于 2024-11-04 19:24:37 发布