面试技巧之带头节点单链表都有哪些例题呢,都整理在这里啦(归并两个带头结点有序链表;两个链表A B, 判断链表B是否为A的子序列;设A B两个链表为带头结点的单链表,且AB升序,求AB的交集)

简介: 面试技巧之带头节点单链表都有哪些例题呢,都整理在这里啦(归并两个带头结点有序链表;两个链表A B, 判断链表B是否为A的子序列;设A B两个链表为带头结点的单链表,且AB升序,求AB的交集)

目录


序言

设A B两个链表为带头结点的单链表,且AB升序,求AB的交集

题目与题目解析,做题步骤

完整代码  

两个链表A B, 判断链表B是否为A的子序列

题目与题目解析,做题步骤

完整代码

归并两个带头结点有序链表

题目与题目解析,做题步骤

完整代码


序言


关于带头结点单链表的构造与创建,可以在博主主页搜索“详细解析单链表带头节点的结构体定义,普通单链表与有序单链表的创建等操作”,即可查看详情,在这篇博文中,我们就直接进入正题啦


正文


设A B两个链表为带头结点的单链表,且AB升序,求AB的交集


题目与题目解析,做题步骤


 设A B两个链表为带头结点的单链表,且 A B升序,求A B的交集。

   A B都有的元素 组成一个新链表C,原 A B不动 ,且C也要升序

   eq:

       A: 1 2 2 3 5 6

       B: 1 1 1 2 2 3  (一样的取一个)

       ==>C: 1 2 3

       dsave = 0

       算法思路:    

           s1:创建一个新的头结点链表C (交集)

           s2:找相同的点 (遍历A和B 找相同的点 相同且不重复 就插入到链表C 不相同 谁小就往后移)

           s3:把相同的点加入到链表头结点

           s4: 把新链表的头结点返回。


完整代码


/*
    common_of_lists:求两个链表的交集
    @listA:链表A
    @listB:链表B
    返回值:
        交集链表C的头结点
*/
List *common_of_lists(List *listA, List *listB)
{
    ElemType dsave = 0;
    Node *pnew = NULL;
    // s1:创建一个新的头结点链表C (交集)
    List *listC = malloc(sizeof(*listC));
    listC->first = NULL;
    listC->last = NULL;
    listC->NodeNum = 0;
    // s2:找相同的点 (遍历A和B 找相同的点 相同且不重复 就插入到链表C 不相同 谁小就往后移)
    Node *pa = listA->first;
    Node *pb = listB->first;
    while(pa && pb)
    {
        if(pa->data == pb->data)// s3:把相同的点加入到链表头结点
        {
            if(pa->data != dsave)//如果该节点与上一个结点的值不重复 就添加到新的链表C中
            {
                pnew = malloc(sizeof(*pnew));
                pnew->data = pa->data;
                pnew->next = NULL;
                if(listC->first == NULL)//从无到有
                {
                    listC->first = pnew;
                    listC->last = pnew;
                }
                else//从少到多尾插
                {
                    listC->last->next = pnew;
                    listC->last = pnew;
                }
                listC->NodeNum++;
                dsave = pa->data;
            }
            pa = pa->next;
            pb = pb->next;
        }
        else if(pa->data < pb->data)//如果不相等 谁小往后走 升序,看后面有没有大一点的值 和现在的值相等
        {
            pa = pa->next;
        }
        else
        {
            pb = pb->next;
        }
    }
    // s4: 把新链表的头结点返回。
    return listC;
}


两个链表A B, 判断链表B是否为A的子序列


题目与题目解析,做题步骤


两个链表A B, 判断链表B是否为A的子序列。

   子序列:连续的一部分

   是:返回1

   不是: 返回0

   A: 1 1 1 2 3 5 6

   B: 1 1 2 3 5

   ==>OK

 

   A: 1 1 2 1 5 5 5 3

   B: 1 2 3

   ==>不ok

 

   算法思路:    

       相等 则继续往下走遍历

       不相等 B回到开头

       长链A 定义一个起始位置 不相等则起始位置往后移一位。


完整代码


/*
    judge_sublist: 判断链表B是否是链表A的子序列
    @listA: A链表
    @listB: B链表
    返回值:
        是子序列 返回1
        不是子序列 返回0
*/
int judge_sublist(List *listA, List *listB)
{
    Node *pa = listA->first;//pa链表A的遍历指针
    Node *pb = listB->first;//pb链表B的遍历指针
    Node *start_a = listA->first;//A链表的起始位置
    while(pa && pb)
    {
        if(pa->data == pb->data)//相等则继续往下遍历
        {
            pa = pa->next;
            pb = pb->next;
        }
        else//不相等 B回到起始位置 pa的位置往下走
        {
            pb = listB->first;//pb回到开头
            start_a = start_a->next;//pa的位置往后走
            pa = start_a;
        }
    }
    if(pb == NULL)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}


归并两个带头结点有序链表


题目与题目解析,做题步骤


   归并两个带头结点有序链表

       合并两个有序的升序链表成一个升序链表

       A:1 2 3 3 5 6

       B:1 5 6

     

       C=> 1 1 2 3 3 5 5 6 6

       算法思路:

           两两比较 取较小的 加入到新链表C中

           step1: 创建一个带头结点的链表C

           step2:两两比较,把较小的结点摘下来

           step3: 把摘下来的结点 加入到链表C

           step4: 返回链表C的头结点


完整代码


List *merge_two_lists(List *listA, List *listB)
{
    //step1: 创建一个带头结点的链表C
    List *listC = malloc(sizeof(*listC));
    listC->first = NULL;
    listC->last = NULL;
    listC->NodeNum = listA->NodeNum + listB->NodeNum;
    Node *pnew = NULL;//指向摘下来的那个结点
    //step2:两两比较,把较小的结点摘下来
    Node *pa = listA->first;
    Node *pb = listB->first;
    while(pa && pb)
    {
        if(pa->data < pb->data)//listA小
        {
            pnew = pa;
            listA->first = listA->first->next;
            pa->next = NULL;
        }
        else//listB小
        {
            pnew = pb;
            listB->first = listB->first->next;
            pb->next = NULL;
        }
        //step3: 把摘下来的结点 加入到链表C
        if(listC->first == NULL)//从无到有
        {
            listC->first = pnew;
            listC->last = pnew;
        }
        else//从少到多
        {
            listC->last->next = pnew;
            listC->last = pnew;
        }
        pa = listA->first;
        pb = listB->first;
    }//end while
    if(pa != NULL)//A链表有剩余
    {
        listC->last->next = listA->first;
        listC->last = listA->last;
    }
    else//B链表有剩余
    {
        listC->last->next = listB->first;
        listC->last = listB->last;
    }
    //step4: 返回链表C的头结点
    return listC;
}
相关文章
|
2天前
|
算法
【优选算法专栏】专题九:链表--------两两交换链表中的节点
【优选算法专栏】专题九:链表--------两两交换链表中的节点
18 0
|
2天前
|
算法
LeetCode刷题---21.合并两个有序链表(双指针)
LeetCode刷题---21.合并两个有序链表(双指针)
链表遍历,链表查找和统计节点,链表插入新节点,链表删除节点,链表修改指定节点,链表头插法,尾插法总结
链表遍历,链表查找和统计节点,链表插入新节点,链表删除节点,链表修改指定节点,链表头插法,尾插法总结
|
2天前
|
存储 Java
高效删除链表倒数节点最优实现
要删除链表的倒数第 n 个节点,并返回链表的头节点,我们可以使用一趟扫描的方法来实现。这个方法涉及使用两个指针:快指针和慢指针。
|
2天前
【力扣】21. 合并两个有序链表
【力扣】21. 合并两个有序链表
|
2天前
|
存储 算法 编译器
【C/C++ 数据结构 线性表】 数据结构 解析 链表中哨兵节点(伪节点)的作用
【C/C++ 数据结构 线性表】 数据结构 解析 链表中哨兵节点(伪节点)的作用
20 0
|
2天前
leetcode2487.从链表中移除节点
leetcode2487.从链表中移除节点
20 1
|
2天前
|
C语言
【C语言】Leetcode 876. 链表的中间节点
【C语言】Leetcode 876. 链表的中间节点
19 0
|
2天前
|
C语言
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
|
2天前
|
设计模式 测试技术
在实现链表的代码中,为什么要使用`Node`类而不是直接在`LinkedList`类中定义节点?
在实现链表的代码中,为什么要使用`Node`类而不是直接在`LinkedList`类中定义节点?
24 1