链表面试题

来源:互联网 发布:福科软件教学 编辑:程序博客网 时间:2024/06/05 08:35
struct node{    int data;    node* next;};//打印有序链表的公共部分void fun1(node* l1, node* l2)//假设是升序{    while (l1&&l2)//知道有一个链表的next指向null    {        if (l1->data > l2->data)//将小值的节点向前移动            l2 = l2->next;        if (l1->data < l2->data)            l1 = l1->next;        if (l1->data == l2->data)//如果值相等,输出然后都向下移        {            cout << l1->data;            l1 = l1->next;            l2 = l2->next;        }       }}
//删除单链表倒数第K个节点node* fun2(node* l, int k){    if (l == nullptr || k <= 0)        return nullptr;    node* cur = l;    while (l)//遍历链表,对K的情况进行分析    {        k--;        cur = cur->next;    }    if (k > 0)//如果K>0,说明没有倒数第K个节点        return l;//,不改变链表,直接返回原链表的头    if (k == 0)//如果K=0, 说明倒数第K个节点就是头结点        l = l->next;//删去头结点,将第二个节点作为头结点    if (k < 0)//当K节点小于零,说明K节点等于零的位置就是要删除节点的迁移个节点    {        cur = l;        while (++k != 0)//当K=0时,k就停在了n-k的位置            cur = cur->next;        cur->next = cur->next->next;//删除第K个节点    }    return l;}
//删除双链表倒数第K个节点dnode* fun3(dnode*l, int k){    if (l == nullptr || k <= 0)//若头结点为空或者K小于0,返回空        return l;    dnode* cur = l;    while (cur)//遍历链表,计算k的情况    {        k--;        l = l->next;    }    if (k > 0)//k大于零,说明没有倒数第K个节点        return l;    if (k == 0)//等于零,说明倒数第K个节点就是头结点    {        l = l->next;        l->last = nullptr;//头结点的last指向空    }    if (k < 0)    {        cur = l;        while (++k!=0)//当K等于零            cur = cur->next;        dnode* newnext = cur->next->next;//删除倒数第K个节点        cur->next = newnext;        if (newnext)            newnext->last = cur;//将此节点的last指向当前节点    }    return l;}
//删除任意n处的节点node* deletenodeab(node*l, int n){    if (n <= 0)        return l;    if (n == 1)        return l;    if (n == 2)        return l->next;//若只有两个节点,删除第一个节点,返回第二个    if (n > 2)    {        node* cur = l;        while (--n != 1)//向前搜索至删除节点的前个节点            cur = cur->next;        cur->next = cur->next->next;//删除节点    }    return l;}
//反转单链表node* reverselist(node*l){    node* pnext = nullptr;    node* pre = nullptr;    while (l)    {        pnext = l->next;//保存l的下一个节点,防断裂        l->next = pre;//将前一个节点变为当前头结点的下一个节点        pre = l;//将pre(前一个节点)前移        l = pnext;//将头节点前移    }    return pre;//返回最新头结点}
//反转双向链表dnode* reversedlist(dnode* l){    dnode* pre = nullptr;    dnode*pnext = nullptr;     while (l)    {        pnext = l->next;//保存当前头结点的下一个节点        l->next = pre;//将当前头结点的前一个节点作为下一个节点        l->last = pnext;//将当前节点的后一个节点指向pnext        pre = l;//pre节点前移        l = pnext;//头结点前移    }    return pre;}
//约瑟夫环问题node* yuesefuhuan(node* l,int m){    if (l == nullptr || l->next == l || m < 1)//头结点为空或者只有一个节点,直接返回        return l;    node* last = l;    while (last->next != l)        last = last->next;    int count = 0;    while (l != last)    {        if (++count == m)//如果报数达到m        {            last->next = l->next;//删除当前节点            count = 0;//计数器重置        }        else            last = last->next;//否则继续报数        l = last->next;    }    return l;}
//判断链表是否回文bool ishuiwen(node*l){    stack<node*> temp;//建立辅助栈    node* p = l;    while (p)//遍历链表,将链表压栈    {        temp.push(p);        p = p->next;    }    while (l)    {        if (l->data != temp.top()->data)//如果链表节点的值和栈节点的值不等,说明不是回文            return false;//返回FALSE        temp.pop();//弹出栈顶元素        l = l->next;//链表前移    }    return true;}
//两个单链表相交的一系列问题//问题一:判断链表是否有环,若有,返回第一个环节点node* getloopnode(node* l){    if (l == nullptr || l->next == nullptr || l->next->next == nullptr)        return nullptr;//包括头节点在内的前三个节点任意为空,则返回空    node* man = l->next;//慢指针    node* kuai = l->next->next;//快指针    while (kuai != man)//寻找相遇节点    {        if (kuai->next == nullptr || kuai->next->next == nullptr)            return nullptr;        man = man->next;//慢指针走一步        kuai = kuai->next;//快指针走两步    }    kuai = l;//相遇之后,快指针重新指向头结点    while (kuai != man)//然后快慢指针都每次走一步,知道相遇,就是入环节点    {        kuai = kuai->next;        man = man->next;    }    return man;//返回入环节点}//如何判断两个无环链表是否相交//问题二:如何判断两个无环链表是否相交node* noloop(node* l1, node* l2){    if (l1 == nullptr || l2 == nullptr)        return nullptr;    node*p1 = l1;    node*p2 = l2;    int n = 0;    while (p1->next)//计算链表1的长度    {        ++n;        p1 = p1->next;    }    while (p2->next)//计算链表二的长度    {        --n;        p2 = p2->next;    }    if (p1 != p2)//如果尾节点不是同一个节点,必然不相交        return nullptr;    p1 = n > 0 ? l1 : l2;//n大于零,说明链表一长度大于链表二    p2 = p1 == l1 ? l2 : l1;    n = abs(n);//返回链表一和链表二的公共长度    while (n-- != 0)//长链表先走完多余长度        p1 = p1->next;    while (p1 != p2)//寻找公共部分的入口节点    {        p1 = p1->next;        p2 = p2->next;    }    return p1;//返回公共部分入口节点}//问题三:判断有环链表是否相交node* doubleloop(node*l1, node*l2, node*loop1, node*loop2){    node* cur1 = nullptr;    node* cur2 = nullptr;    if (loop1 == loop2)//若入环节点相同,则类似于问题二    {        cur1 = l1;        cur2 = l2;        int n = 0;        while (cur1 != loop1)//找到loop1的前一个节点        {            ++n;//统计链表1的数目            cur1 = cur1->next;        }        while (cur2 != loop2)//找loop2的前一个节点        {            --n;//判断这两个链表的数目哪个多            cur2 = cur2->next;        }        cur1 = n > 0 ? l1 : l2;//n大于零,说明链表1长,否则说明链表二长        cur2 = cur1 == l1 ? l2 : l1;        n = abs(n);//求取多余节点数目        while (n-- != 0)//走完多余长度            cur1 - cur1->next;        while (cur1 != cur2)//寻找公共节点        {            cur1 = cur1->next;            cur2 = cur2->next;        }        return cur1;    }    else    {        cur1 = loop1->next;        while (cur1!=loop1)//遍历环上节点        {            if (cur1 == loop2)//若发现了链表二的入环节点,说明有公共部分并返回                return loop1;            cur1 = cur1->next;        }        return nullptr;//否则无公共节点    }}
//合并两个有序单链表node* mergetwo(node* l1, node*l2){    if (l1 == nullptr)        return l2;    if (l2 == nullptr)        return l1;    node*p = nullptr;    if (l1->data > l2->data)//比较两个链表当前节点值得大小    {        p = l2;//若l1大,则把l2作为链表的头结点        p->next = mergetwo(l1, l2->next);//在l1和l2的下一个节点之间继续挑选节点值小的    }    if (l1->data < l2->data)    {        p = l1;        p->next = mergetwo(l1->next, l2);    }    return p;//返回新链表的头结点}
//按照左右半区重新组合单链表void mergelr(node* l, node* r)//合并{    node*next = nullptr;    while (l->next)    {        next = r->next;        r->next = l->next;        l->next = r;        l = r->next;        r = next;    }    l->next = r;}void regroup(node*l)//分离两个链表{    if (l == nullptr || l->next == nullptr)        return;    node* mid = l, *right = l->next;    while (right->next&&right->next->next)//快慢指针查找中间节点    {        mid = mid->next;        right = right->next->next;    }    right = mid->next;//将链表分为两个链表    mid->next = nullptr;    mergelr(right, l);//重新组合}
//向有序环形单链表中插入新节点node* insertnode(node* l, int num){    node*q = (node*)malloc(sizeof(struct node*));//分配新节点    q->data = num;//对新节点赋值    if (l == nullptr)//若头结点为空,新节点自己组成单循环链表    {        q->next = q;        return q;    }    node* p = l->next;    while (p!=l)//遍历    {        if (p->data <= num&&p->next->data >= num)//发现插入节点的位置        {            q->next = p->next;//插入节点            p->next = q;            break;        }        p = p->next;    }    return l->data > num ? q : l;    //因为链表有序,若新节点的值大于头结点,直接返回头结点,若小于,返回新节点(新的头结点)}
//一种怪异的删除节点方式void deletenodewire(node* n){//本质上不是伤处节点,而是将给定节点的下一个节点的值对当前节点进行覆盖,然后删除下一个节点    if (n == nullptr)        return;    node*p = n->next;    n->data = p -> data;    n->next = p->next;}
//删除链表中的重复节点(保留重复节点)node* deleterepeatnodes(node*l){    node* cur = l;    node*pre = nullptr;    node*next = nullptr;    while (cur)    {        pre = cur;        next = cur->next;         while (next)        {            if (cur->data == next->data)//发现相邻节点值相等                pre->next = next->next;//删除            else                pre = next;//否则依次前进            next = next->next;        }        cur = cur->next;//当前节点进行一次循环之后,前移一个节点    }    return l;}
//删除链表指定值节点node *deletethatnode(node*l, int num){    if (l->next == nullptr || l == nullptr)        return l;    while (l)//防止头结点就是要删除的节点    {        if (l->data != num)            break;        l = l->next;//重新定义头结点    }    node*cur = l;    node*pre = l;    while (cur)    {        if (cur->data == num)            pre->next = cur->next;        else            pre = cur;        cur = cur->next;    }    return l;}
//从尾到头打印链表    vector<int> printListFromTailToHead(ListNode* l) {        ListNode* p=reverse(l);        vector<int> res;        while(p)            {            res.push_back(p->val);            p=p->next;        }        return res;    }    ListNode* reverse(ListNode* l)        {        if(l==nullptr||l->next==nullptr)            return l;        ListNode* pre=nullptr;        ListNode* next=nullptr;        ListNode* cur=l;        while(cur)            {            next=cur->next;            cur->next=pre;            pre=cur;            cur=next;        }        return pre;    }
0 0
原创粉丝点击