LeetCode-链表相关面试题(一)

一,相交链表(160题)

1 题目要求:编写一个程序,找到两个单链表相交的起始节点。

2 题目描述

传入两个链表,判断是否相交,如果相交,返回相交位置的结点。例如本例返回c1结点,如果不相交,返回NULL

例如:该例子相交,所以返回 8 这个结点

例如:该例子,两个链表不相交,返回NULL

3 分析题目实现过程 :1,首先求两条链表的长度,

2,求出两条链表长度的差size,

3,定义两个指针,分别指向两个链表的头结点,

4,让长链表的指针先往后走 size步,

5,让两个指针同时往后走,比较每个结点,判断结点是否相同,

6,如过结点相同,就返回该结点,

7,否则,返回NULL。

4 代码实现 : 

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
	struct ListNode* pA1 = headA, *pA2 = headA;
	struct ListNode* pB1 = headB, *pB2 = headB;
	int lengthA = 0;
	int lengthB = 0;
	while (pA1 != NULL) {
		lengthA++;
		pA1 = pA1->next;
	}
	while (pB1 != NULL) {
		lengthB++;
		pB1 = pB1->next;
	}
	int size = (lengthA>lengthB) ? (lengthA - lengthB) : (lengthB - lengthA);
	if (lengthA >= lengthB) {
		for (int i = 0; i<size; i++) {
			pA2 = (pA2->next);
		}
		while (pA2 != NULL && pB2 != NULL) {
			if (pA2 == pB2) {
				return pA2;
			}
			pA2 = pA2->next;
			pB2 = pB2->next;
		}
		return NULL;
	}
	else {
		for (int i = 0; i < size; i++) {
			pB2 = (pB2->next);
		}
		while (pB2 != NULL &&pA2 != NULL) {
			if (pB2 == pA2) {
				return pB2;
			}
			pA2 = pA2->next;
			pB2 = pB2->next;
		}
		return NULL;
	}
}

二,删除链表元素(203题)

题目要求 : 删除链表中等于给定值 val 的所有节点。

题目描述 :

   

   传入一个链表,在该函数中操作之后,删除所有指定结点,然后返回链表,例如:该例子,传入第一个结点的地址,删除val = 6的结点之后,返回指向第一个结点的指针。

分析题目实现过程:1,首先判断传入的链表是否为空,如果为空,返回NULL,

2,如果不为空,开始从第二个结点遍历,比较结点的值是否等于val,如过等于,删除结点,否则,继续循环,

      这块注意如果删除结点,删除完结点之后一定要在 cur = cur->next 之前继续一次循环,否则少比较了一个结点。

3,判断第一个结点的值是否等于 val ,如果等于,保存第二个结点,删除第一个结点,返回第二个结点的地址,

4,否则返回第一个结点的地址。

代码实现

struct ListNode* removeElements(struct ListNode* head, int val) {
	if (head == NULL) {
		return NULL;
	}
	struct ListNode* cur = head;
	while (cur->next != NULL) {
		struct ListNode* next = cur->next;
		if (cur->next->val == val) {
			cur->next = cur->next->next;
			free(next);
			continue;
		}
		cur = cur->next;
	}
	if (head->val == val) {
		struct ListNode* next = head->next;
		free(head);
		return next;
	}
	return head;
}

三,删除链表中的结点(237题)

题目要求:请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

题目描述

传入一个链表。调用了我们的函数之后,删除了node结点。

分析题目实现过程:因为无法知道node的上一个结点,所以只能将node后面结点的值赋给node结点,然后删除node后面的结点。

代码实现

void deleteNode(struct ListNode* node) {
	struct ListNode* next = node->next;
	node->val = node->next->val;
	node->next = node->next->next;
	free(next);
}

四,反转链表(206题)

题目要求  : 反转一个单链表.

题目描述  : 

  

传入一个链表。将链表逆置之后返回。

分析题目实现过程 :定义两个指针,一个 cur 指向链表头结点,一个 prev 设置为空,如果 cur 不为空,就记录下 cur 后面的结

点为 next,将 cur 的 next 置为 prev 然后更改 cur 为 next ,prev 改为 cur ,然后继续循环,直到条件不满足(cur == NULL),

返回 prev 的地址。

代码实现 : 

struct ListNode* reverseList(struct ListNode* head) {
	struct ListNode* cur = head;
	struct ListNode* prev = NULL;
	while (cur != NULL) {
		struct ListNode* next = cur->next;
		cur->next = prev;
		prev = cur;
		cur = next;
	}
	return prev;
}

五,分隔链表(86题)

题目要求

给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。应当保留两个分区中每个节点的初始相对位置。

题目描述

传入一个链表,传入一个参数x,拿链表中的每一个结点的值和x做比较,如果小于x,就依次按照原链表顺序放在大于等于x 的前面。

分析题目实现过程:1,首先创建两个的结点 t1, t2,用来作为保存小于 和 大于等于 x值结点的新链表的头结点。

2,分别定义两个指针变量temp1,temp2用来操作t1,t2,

3,用原链表的每一个结点的值和 x 做比较,小于x 的话,就将结点放在t1后面,否则,放在t2 后面,

4,原链表比较完之后,把连个链表连接起来,释放掉申请的两个结点的内存。返回新的链表。

代码实现

struct ListNode* partition(struct ListNode* head, int x) {
	if (head == NULL) {
		return NULL;
	}
	struct ListNode* t1 = (struct ListNode*)malloc(sizeof(struct ListNode));
	struct ListNode* t2 = (struct ListNode*)malloc(sizeof(struct ListNode));
	struct ListNode* temp1 = t1;
	struct ListNode* temp2 = t2;
	while (head != NULL) {
		if (head->val < x) {
			temp1->next = head;
			temp1 = temp1->next;
		}
		else {
			temp2->next = head;
			temp2 = temp2->next;
		}
		head = head->next;
	}
	temp2->next = NULL;
	temp1->next = t2->next;
	temp1 = t1->next;
	free(t1);
	free(t2);
	return temp1;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章