链表习题(二)

1.查找单链表的倒数第K个节点

  • 设置两个指针(一个记为快指针,一个记为慢指针),都先指向头节点
  • 让快指针先走k-1步
  • 快、慢指针都一步一步往下走,知道快指针为空,慢指针所在位置就是K节点所在位置
struct ListNode* FindKthToTail(struct ListNode* PListHead, unsigned int k) {
	if (PListHead == NULL) { return null; }
	struct ListNode *front = PListHead;
	struct ListNode *back = PListHead;
	//让前面的先走k-1步
	for (int i = 0; i < k-1; i++) {
		front = front->next;
	}
	while (front != NULL) {
		front = front->next;
		back = back->next;
	}
	return back;
}

2.在一个排序的链表中,删除该链表中重复的结点,重复的结点不保留,返回链表头指针

  1. 先设置3个指针,prev指向头节点、p1也指向头节点,p2指向头节点的下一个节点
  2. 比较p1和p2的值是否相等,若不相等,则三个指针都往后走一步;若相等,则p2指针往后走一步,其他两个指针不动,直到p2指针走到下一个不相等的位置。
  3. 删重复节点(p1到p2指针指向的前一个节点都是重复的)
  4. 设置一个节点,它的一个地址的指向为头节点(因为若头节点也是重复节点,早被删除)
struct ListNode* deleteDuplication(struct ListNode* pHead) {
	if (pHead == NULL) { return NULL; }
	struct ListNode *fake = (struct ListNode *)malloc(sizeof(struct ListNode));
	fake->next = pHead;//假结点

	struct ListNode *prev = fake;
	struct ListNode *p1 = pHead;
	struct ListNode *p2 = pHead->next;

	while (p2 != NULL) {
		if (p1->val != p2->val) {
			prev = p1; p1 = p2; p2 = p2->next;
		}
		else {
			while (p2 != NULL && p2->val == p1->val) {
				p2 = p2->next;
			}
			struct ListNode *cur = p1;
			while (cur != p2) {
				struct ListNode *next = cur->next;
				free(cur);
				cur = next;
			}
			prev->next = p2;
			p1 = p2;
			if (p2 != NULL) { p2 = p2->next; }
		}
	}
	pHead = fake->next;
	free(fake);
	return pHead;
}

3.找两个单链表的交点

  1. 先求两个链表相差的长度。
  2. 设置两个指针(快、慢指针问题)
  3. 快指针先走相差的长度-1步,如果快、慢指针不相等,则快、慢指针各往后走一步
  4. 返回快指针
int getLength(struct ListNode *head) {
	int len = 0;
	for (struct ListNode *n = head; n; n = n->next) {
		len++;
	}
	return len;
}
struct ListNode* getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
	int lenA = getLength(headA);
	int lenB = getLength(headB);

	struct ListNode *longer = headA;
	struct ListNode *shorter = headB;
	int diff=lenA - lenB;
	if (lenB > lenA) {
		longer = headB;
		shorter = headA;
		diff = lenB - lenA;
	}
	for (int i = 0; i < diff; i++) {
		longer = longer->next;
	}
	while (longer != shorter) {
		longer = longer->next;
		shorter = shorter->next;
	}
	return longer;
}

4.复杂链表的复制

一个链表的每个结点,有一个指向next指针指向下一个结点,还有一个random指针指向这个链表的随机结点或者NULL,返回复制后的新链表。
定义复杂链表的结构

typedef struct RNode {
    int val;
    struct RNode *next;
    struct RNode *random;
}RNode;

RNode* Copy(RNode* head) {
	//1.只复制结点中的value和next,让新结点跟在老结点后边
	//2.再处理random复制
	//3.把链表拆成两个
	if (head == NULL) { return NULL; }
	RNode *oldNode = head;
	while (oldNode != NULL) {
		RNode *newNode = (RNode*)malloc(sizeof(RNode));
		newNode->val = oldNode->val;

		RNode *oldNext = oldNode->next;
		newNode->next = oldNext;
		oldNode->next = newNode;

		oldNode = oldNext;

		oldNode = head;
		while (oldNode != NULL) {
			RNode *newNode = oldNode->next;
			if (oldNode->random == NULL) {
				newNode->random = NULL;
			}
			else {
				newNode->random = oldNode->random->next;
			}
			oldNode = newNode->next;

		}
		oldNode = head;
		newNode = head->next;
		while (oldNode != NULL) {

			RNode *newNode = oldNode->next;
			oldNode->next = newNode->next;
			if (newNode->next != NULL) {
				newNode->next = newNode->next->next;
			}
			oldNode = oldNode->next;
		}
		return newNode;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值