专题复习二:链表(1)

链表是笔试中最常考的一类题目

(1)剑指 Offer 24. 反转链表

要实现链表的翻转,一定需要三个临时节点,否则无法实现翻转,即利用三个指针

方法一:不构建新的节点

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head) return NULL;
        ListNode *p = head->next;
        if(!p) return head;
        ListNode *q = p->next;
        head->next = NULL;
        while(q)
        {
            p->next = head;
            head = p;
            p = q;
            q = q->next;
        }
        p->next = head;
        return p;
    }
};

方法二:构建新的节点

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *pre = NULL;
        ListNode *cur = head;
        while(cur)
        {
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;

    }
};

剑指 Offer 22. 链表中倒数第k个节点

需要前后两个节点,利用双指针

class Solution {
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
        ListNode *pre = head;
        ListNode *cur = head;
        while(cur)
        {
            cur=cur->next;
            if(k>0) k--;
            else pre=pre->next;
        }
        return pre;
    }
};

剑指 Offer 52. 两个链表的第一个公共节点

需要两个节点分别遍历两个链表,双指针

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* A = headA;
        ListNode* B = headB;
        while(A!=B)
        {
            A = A==NULL? headB: A->next;
            B = B==NULL? headA: B->next;
        }
        return A;
        
    }
};

剑指 Offer 18. 删除链表的节点

类似翻转链表,也是利用三个指针

class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        if(val == head->val) return head->next;
        ListNode *virHead = new ListNode(0);
        virHead->next = head;
        ListNode *pre = head;
        ListNode *cur = head;
        while(cur)
        {
            ListNode *next = cur->next;
            if(cur->val!= val) //继续向后遍历
            {
                pre = cur;
                cur = next;
            }
            else               //说明已经找到该节点 执行删除节点操作
            {
                pre->next = next;
                return virHead->next;
            }
        }
        return NULL;

    }
};

剑指 Offer 06. 从尾到头打印链表

这里利用辅助栈,根据栈先入后出的特点 先用栈依次将数组存起来,然后在依次出栈,放入到数组res中

注意 判断stack不为空 用empty()   

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        if(!head) return {};
        stack<int> a;
        while(head)
        {
            a.push(head->val);
            head=head->next;
        }
        vector<int> res;
        while(!a.empty())
        {
            res.push_back(a.top());
            a.pop();
        }
        return res;
    }
};

leetcode 21. 合并两个有序链表

方法一:利用迭代

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *virHead = new ListNode(-1);
        ListNode * a = virHead;
        while(l1&&l2)
        {
            virHead->next = (l1->val <= l2->val)? l1: l2;
            virHead = virHead->next;
            if(l1->val<=l2->val) l1= l1->next;
            else l2 = l2->next;
        }
        virHead->next = l1==nullptr? l2:l1;
        return a->next;

    }
};

方法二:利用递归 递归类似栈的先进后出

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(!l1) return l2;
        else if(!l2) return l1;
        else if(l1->val <= l2->val)
        {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }
        else
        {
            l2->next = mergeTwoLists(l2->next, l1);
            return l2;
        }
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值