一,相交链表(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;
}