牛客网面试必刷TOP101——链表(一)

1.反转链表

在这里插入图片描述这题我使用的是直接将最前面的节点放置到最后,然后然后遍历整个链表的方法。

class Solution {
  public:
    ListNode* ReverseList(ListNode* head) {
        ListNode* newhead = nullptr;/设立一个新的头结点
        while (head) {
            ListNode* temp = head->next;/存储头结点后面的节点
            head->next = newhead;/将存储的反转链表接上去
            newhead = head;/存储最前面的节点到newhead
            head = temp;/将被夺走了头节点的链表又放回来
        }
        return newhead;
    }
};

2.链表内指定区间反转

在这里插入图片描述遍历到n的位置,然后在n到m之间执行反转链表的操作。

class Solution {
  public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* a = new ListNode(-1);
        a->next = head;
        ListNode* b = a;
        ListNode* c = head;
        for (int i = 1; i < m ; i++) {/遍历到n的位置
            b = c;
            c = c->next;
        }
        ListNode* e = nullptr;
        ListNode* f = nullptr;
        for (int i = m; i < n; i++) {
            f = b -> next;
            e = c -> next;
            b -> next = e;/将第一个节点后面的节点一个一个拿到前面去
            c -> next = e->next;
            e -> next = f;
        }
        return (a->next);
    }
};

3.链表中的节点每k个一组反转

在这里插入图片描述这题就开始用聪明点的方法了,反转这种操作其实应该马上想到栈,这题就是使用栈来进行操作的。

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        stack<int> s;
        ListNode* temp=head;
        ListNode* re=temp;
        while(head!=NULL){
        for(int i=0;i<k;i++){/每k个输出一次
            s.push(head->val);
            head=head->next;
            if(head==NULL){
                if(i<k-1) return re;
                else break;
            }
        }
        while(!s.empty()){
            temp->val=s.top();
            s.pop();
            temp=temp->next;
        }
        }
        return re;
    }
};

4.合并两个排序的链表

在这里插入图片描述这题之前在滴滴面试真题里做过,使用双指针就可以了。

class Solution {
  public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        // write code here
        ListNode* temp = new ListNode(0);
        ListNode* out = temp;
        while (pHead1 != NULL && pHead2 != NULL) {
            if (pHead1->val <= pHead2->val) {
                temp->next = pHead1;
                pHead1 = pHead1->next;
            }
            else {
                temp->next = pHead2;
                pHead2 = pHead2->next;
            }
            temp = temp->next;
        }
        if (pHead1) temp->next = pHead1;
        if (pHead2) temp->next = pHead2;
        return out->next;
    }
};

5.合并k个已排序的链表

在这里插入图片描述这题我是将两个链表相加写成了函数,然后再调用。

#include <cstddef>
class Solution {
  public:
    ListNode* add(ListNode* i, ListNode* j) {
        ListNode* tmp = new ListNode(0);
        ListNode* out = tmp;
        while (i != NULL && j != NULL) {
            if (i->val <= j->val) {
                tmp->next = i;
                i = i->next;
            } else {
                tmp->next = j;
                j = j->next;
            }
            tmp = tmp->next;
        }
        while (i) {
            tmp->next = i;
            i = i->next;
            tmp = tmp->next;
        }
        while (j) {
            tmp->next = j;
            j = j->next;
            tmp = tmp->next;
        }
        return out->next;
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* cum = nullptr;
        if(lists.size()==0) return 0;
        for (int i = 0; i < lists.size(); i++) {
            cum = add(cum, lists[i]);
        }
        return cum;
    }
};

6.判断链表中是否有环

在这里插入图片描述这题使用快慢指针即可,只要它们能相等,那么就代表有环。

#include <type_traits>
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;/快慢指针
        ListNode* slow = head;
        while(fast!=nullptr&&fast->next!=nullptr){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow) return true;
        }  
        return false;
    }
};

7.链表中环的入口节点

在这里插入图片描述先快慢指针,然后将快指针变慢从头再来,就可以确定入口了。

class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        ListNode* fast = pHead;
        ListNode* slow = pHead;
        while(fast!=nullptr&&fast->next!=nullptr){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow) break;
        }
        if(fast==nullptr||fast->next==nullptr){
            return nullptr;
        }
        else{
            fast=pHead;
            while(fast!=slow){
                fast=fast->next;
                slow=slow->next;
            }
            return fast;
        } 
    }
};

8.链表中倒数最后k个节点

在这里插入图片描述遍历过去就可以了。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pHead, int k) {
        // write code here
        int i=0;
        ListNode* tmp = pHead;
        while(pHead){
            pHead=pHead->next;
            i++;
        }
        if(k>i) return nullptr;
        for(int j=0;j<i-k;j++){
            tmp=tmp->next;
        }
        return tmp;
    }
};

谢谢观看!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值