链表相关面试题(详细注释)LeetCode亲测无误

1、合并两个有序链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(l1==NULL)//如果链表1为空的话,那么合并后的链表是l2,所以返回l2
    {
        return l2;
    }
    if(l2==NULL)
    {
         return l1;//如果链表2为空的话,那么合并后的链表是l1,所以返回l1
    }
    struct ListNode *c1 = l1;//定义链表1
	struct ListNode *c2 = l2;//定义链表2
	struct ListNode *result = NULL;//新链表的第一个结点
	struct ListNode *tail = NULL;//新链表的最后一个结点
    while(c1!=NULL&&c2!=NULL)//如果两个链表都不为空的话,循环继续
    {
        if(c1->val<=c2->val)//判断链表1和链表2中的值大小,如果链表1中的数字小于等于链表2中       的数值
        {
            if(tail!=NULL)//新链表的最后一个结点不为空的话,就尾插
            {
                tail->next=c1;
                tail=c1;
            }
            else//走到这里,说明新链表的最后一个结点为空
            {
                result=tail=c1;//新链表最后一个结点为空的话,此时就把链表1赋给新链表
            }
            c1=c1->next;
         }
        else//如同上边,只是把c1换成c2就可以
        {
           if(tail!=NULL)//新链表的最后一个结点不为空的话,就尾插
            {
                tail->next=c2;
                tail=c2;
            }
            else
            {
                result=tail=c2;//新链表最后一个结点为空的话
            }
            c2=c2->next; 
        }
    }
    if(c1!=NULL)//走到这里说明c1没有遍历完,剩下的直接尾插即可
    {
        tail->next=c1;
    }
    if(c2!=NULL)
    {
        tail->next=c2;
    }
    return result;
}

2、链表逆置

struct ListNode* reverseList(struct ListNode* head)
{
	struct ListNode *current = head;//定义一个用于遍历的指针变量,从头结点开始
	struct ListNode *prev = NULL;//定义头结点的前驱结点
	while (current != NULL)//开始遍历
	{
		struct ListNode *next = current->next;//先把它保存起来,防止next指向关系发生变化之后,找不到下一个结点的地址了
		current->next = prev;//让当前指针的指向指向他的前一个结点,这样就形成了逆置,注意的是结点只能指向一个地方
		prev = current;
		current = next;
	}
	return prev;
}

3、分隔链表
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。

示例:

输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5

struct ListNode* partition(struct ListNode* head, int x){
    struct ListNode* small=NULL;//定义一个用于保存比x小的数的链表
    struct ListNode* smallLast=NULL;//小链表的最后一个数(空间)
    struct ListNode* big=NULL;//定义一个用于保存比x大的链表
    struct ListNode* bigLast=NULL;//大链表的最后一个数(空间)
    struct ListNode* cur=head;//用于遍历
    while(cur!=NULL)//遍历整个原始链表
    {
        if(cur->val<x)//如果小于x的
        {//以下为链表的尾插,尾插就要分两种情况
            if(small==NULL)//如果小链表为空
            {
                small=smallLast=cur;
            }
            else//如果不为空
            {
                smallLast->next=cur;
                smallLast=cur;//最后一个值发生改变,需要更新,这里小编也很容易忘记呢
            }
        }
        else//以下代码同上,只不过把小链表换成大链表就可以啦
        {
            if(big==NULL)
            {
                big=bigLast=cur;
            }
            else
            {
               bigLast->next=cur;
               bigLast=cur;//最后一个值发生改变,需要更新
            } 
        }
        cur=cur->next;//链表能走起来的条件
    }
    //以下小细节也不容忽视哈
    if(smallLast!=NULL)
    {
        //如果比x小的链表有结点,则把两个链表连起来
         smallLast->next=big;
    }
    if(bigLast!=NULL)
    {
        //如果比x大的链表有结点,则最后一个结点->next=NULL
     bigLast->next=NULL;
    }
    if(smallLast!=NULL)
    {
        //有小链表从小的返回
        return small;
    }
    else
    {//否则从大的返回
       return big;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值