1.合并两个有序链表
解决方法有两种:
新建一个链表,然后分别遍历两个链表,每次都选最小的结点接到新链表上,最后排完。另外一个就是将一个链表结点拆下来,逐个合并到另外一个对应位置上去。
这里采用第一种:
(1)创建一个空表list3
(2)依次从list1或list2中选取元素值较小的结点插入到list3的最后,直到其中一个表变空为止
(3)继续将list1或list2其中一个表的剩余结点插入到list3的最后
代码如下:
struct ListNode* mergeTowLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode *newHead = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *res = newHead;
while (list1 && list2) {
if (list1->val < list2->val) {
newHead->next = list1;
list1 = list1->next;
}
else if(list1->val>list2->val){
newHead->next = list2;
list2 = list2->next;
}
else {
newHead->next = list2;
list2 = list2->next;
newHead = newHead->next;
newHead->next = list1;
list1 = list1->next;
}
newHead=newHead->next;
}
while (list1) {
newHead->next = list1;
list1 = list1->next;
newHead=newHead->next;
}
while (list2) {
newHead->next = list2;
list2 = list2->next;
newHead=newHead->next;
}
return res->next;
}
完整代码:
#include<stdlib.h>
#include<stdio.h>
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode *initList(const int array[],int size) {
struct ListNode *newHead = (struct ListNode*)malloc(sizeof(struct ListNode));
newHead->next = NULL;
struct ListNode *res = newHead;
for (int i = 0; i < size; i++) {
struct ListNode* q = (struct ListNode*)malloc(sizeof(struct ListNode));
q->val = array[i];
q->next = newHead->next;
newHead->next = q;
newHead = newHead->next;
}
return res->next;
}
void printList(struct ListNode *p) {
struct ListNode *temp = p;
while (temp) {
//struct ListNode* f = temp;
printf("%d", temp->val);
temp = temp->next;
//free(f);
}
printf("\n");
}
struct ListNode* mergeTowLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode *newHead = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *res = newHead;
while (list1 && list2) {
if (list1->val < list2->val) {
newHead->next = list1;
list1 = list1->next;
}
else if(list1->val>list2->val){
newHead->next = list2;
list2 = list2->next;
}
else {
newHead->next = list2;
list2 = list2->next;
newHead = newHead->next;
newHead->next = list1;
list1 = list1->next;
}
newHead=newHead->next;
}
while (list1) {
newHead->next = list1;
list1 = list1->next;
newHead=newHead->next;
}
while (list2) {
newHead->next = list2;
list2 = list2->next;
newHead=newHead->next;
}
return res->next;
}
int main() {
struct ListNode* list1 = NULL;
struct ListNode* list2 = NULL;
printf("creat list: \t\n");
int a[] = { 1,2,3 };
int b[] = { 1,3,4 };
list1 = initList(a, 3);
list2 = initList(b, 3);
struct ListNode *list3 = mergeTowLists(list1, list2);
printList(list3);
return 0;
}
优化代码:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
struct ListNode* prehead = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* prev = prehead;
while (list1 && list2)
{
if (list1->val <= list2->val)
{
prev->next = list1;
list1 = list1->next;
}
else
{
prev->next = list2;
list2 = list2->next;
}
prev = prev->next;
}
prev->next = list1 == NULL ? list2 : list1;
return prehead->next;
}
2.合并K个链表
先将前两个合并,之后再将后面的逐步合并起来。
代码如下:
struct ListNode* mergeKLists(struct ListNode* lists[],int size){
struct ListNode* res=NULL;
for(int i=0;i<size;i++){
res=mergeTowLists(res,lists[i]);
}
return res;
}
3.LeetCode1669
题目:给你两个链表list1和list2,它们包含的元素分别为n个和m个。请你将list1中下标从a到b的结点删除,并将list2接在被删除结点的位置。
题目意思:将list1中的[a,b]区间删掉,然后将list2接进去,如下图所示:
代码如下:
struct ListNode *mergeInBetween(struct ListNode *list1, int a, int b, struct ListNode *list2)
{
struct ListNode *pre1 = list1;
struct ListNode *post1 = list1;
struct ListNode *post2 = list2;
int i = 0, j = 0;
// 寻找list1中的节点pre1和post1
while (pre1 != NULL && post1 != NULL && j < b)
{
if (i != a - 1)
{
pre1 = pre1->next;
i++;
}
if (j != b)
{
post1 = post1->next;
j++;
}
}
post1 = post1->next;
// 寻找list2的尾节点
while (post2->next != NULL)
{
post2 = post2->next;
}
// 链1尾接链2头,链2尾接链1后半部分的头
pre1->next = list2;
post2->next = post1;
return list1;
}
注意:题目中开闭区间的情况。