链表类题目

/*问题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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值