算法设计题:
1.将两个递增的有序链表合并为一个递增的有序链表。要求结构链表仍使用原来两个链表的存储空间,不另外占用其他的存储空间,表中不允许有重复的数据
答:问题分析: 给定两个递增的有序链表,我们需要将它们合并为一个递增的有序链表,并且要求合并后的链表仍然使用原来的两个链表的存储空间。我们可以通过比较两个链表的节点值的大小来实现合并。
解决过程:
- 定义一个辅助指针p,指向两个链表中的较小值的节点。
- 将较小值的节点从原链表中移除,并将p指向下一个节点。
- 重复步骤2,直到其中一个链表为空。
- 将非空链表剩余的部分直接连接到p的后面。
- 返回合并后的链表。
代码实现:
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构
typedef struct ListNode {
int val;
struct ListNode* next;
} ListNode;
// 创建链表节点
ListNode* createNode(int val) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->val = val;
node->next = NULL;
return node;//node为ListNode*类型指针
}
// 合并两个有序链表
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == NULL) {
return l2;
}//一个链表为空时,合并后即为另一链表
if (l2 == NULL) {
return l1;
}
// 定义一个辅助指针p
ListNode* p;
if (l1->val < l2->val) {
p = l1;
l1 = l1->next;
} else {
p = l2;
l2 = l2->next;
}
ListNode* head = p; // 合并后的链表的头节点,为两链表首节点小的一个
// 比较两个链表的节点值,不断更新辅助指针p的指向
while (l1 != NULL && l2 != NULL) {
if (l1->val < l2->val) {
p->next = l1;
l1 = l1->next;//由小到大给p->next赋值
} else {
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
// 将非空链表剩余的部分直接连接到p的后面
if (l1 != NULL) {
p->next = l1;
}
if (l2 != NULL) {
p->next = l2;
}
return head;
}
// 打印链表
void printList(ListNode* head) {
ListNode* p = head;
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
}
int main() {
// 创建两个有序链表
ListNode* l1 = createNode(1);
l1->next = createNode(2);
l1->next->next = createNode(4);
ListNode* l2 = createNode(1);
l2->next = createNode(3);
l2->next->next = createNode(4);
// 合并两个链表
ListNode* mergedList = mergeTwoLists(l1, l2);
// 打印合并后的链表
printList(mergedList);
return 0;
}
2.将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个A,B的交集,并存放在A链表
答:
问题分析: 给定两个非递减的有序链表A和B,我们需要将它们合并为一个非递增的有序链表,并且要求结果链表仍然使用原来的A链表的存储空间。我们可以通过比较两个链表的节点值的大小来实现合并,并将较大值的节点插入到A链表的前面。新链表中的元素从大到小依次排列。
解决过程:
- 如果A链表为空,直接将B链表连接到A链表,并返回A链表。
- 定义一个辅助指针p,指向A链表的头节点。
- 循环比较A链表和B链表的节点值的大小,直到其中一个链表为空。
- 如果A链表的节点值小于等于B链表的节点值,将p指向下一个节点。
- 如果A链表的节点值大于B链表的节点值,插入B链表的节点到A链表的前面,并更新p指向插入的节点。
- 将B链表剩余的部分直接连接到A链表的前面。
- 返回合并后的A链表。
代码实现:
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构
typedef struct ListNode {
int val;
struct ListNode* next;
} ListNode;
// 创建链表节点
ListNode* createNode(int val) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->val = val;
node->next = NULL;
return node;
}
// 合并两个非递减的有序链表
ListNode* mergeTwoLists(ListNode* A, ListNode* B) {
if (A == NULL) {
return B;
}
if (B == NULL) {
return A;
}
// 定义一个辅助指针p,指向A链表的头节点。较小值为头
ListNode* p = A;
// 循环比较A链表和B链表的节点值的大小
while (A != NULL && B != NULL) {
if (A->val <= B->val) {
p = A;
A = A->next;
} else {
ListNode* temp = B;
B = B->next;
temp->next = p;
p = temp;
}
}
// 将B链表剩余的部分直接连接到A链表的前面
if (B != NULL) {
ListNode* temp = B;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
p = B;
}
return p;
}
// 打印链表
void printList(ListNode* head) {
ListNode* p = head;
while (p != NULL) {
printf("%d ", p->val);
p = p->next;
}
printf("\n");
}
int main() {
// 创建两个非递减的有序链表
ListNode* A = createNode(1);
A->next = createNode(3);
A->next->next = createNode(5);
ListNode* B = createNode(2);
B->next = createNode(4);
B->next->next = createNode(6);
// 合并两个链表
ListNode* mergedList = mergeTwoLists(A, B);
// 打印合并后的链表
printList(mergedList);
return 0;
}