C++刷题笔记9:链表

P.S 非科班出身,对C++和算法较陌生,从入门开始,使用Leetcode平台,借鉴了很多前人的思路,博客仅为记录用。
本期打卡链表的三道题目:对应<剑指 Offer 06. 从尾到头打印链表><剑指 Offer 24. 反转链表><剑指 Offer 35. 复杂链表的复制>

问题10:从尾到头打印链表

问题描述:输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
问题要求:无
解题思路:这道题的要求是返回每个节点的值,而不是返回反过来的链表:一个自然的思路是使用栈从头到尾保存链表的节点值,然后再从栈顶到栈底依次取出值。
代码

/**
 1. Definition for singly-linked list.
 2. struct ListNode {
 3.     int val;
 4.     ListNode *next;
 5.     ListNode(int x) : val(x), next(NULL) {}
 6. };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        stack<int> temp;
        vector<int> result;
        int i = 0;
        while (head != nullptr){
            temp.push(head->val);
            head = head->next;
        }
        while (!temp.empty()){
            result.push_back(temp.top());
            i=i+1;
            temp.pop();
        }
    return result;
    }
};

注意点

  1. 栈的声明:stack<int> temp;数组的声明vector<int> result;数组加入数值result.push_back(temp.top());

参考资料:

  1. 剑指offer06

问题11:反转链表

问题描述:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
问题要求:无
解题思路:这道题相当于比上一题更进一步,一个思路是递归。
主要策略:递归
a->b->c->d->e要变成a<-b<-c<-d<-e
可以为
a<-(b<-c<-d<-e)
即为
而将a->b变为a<-b要经历的包括:
(1) a->b->a;
(2) a->nullptr;即b->a->nullptr.
从尾部开始递归。

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* new_head;
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr){
            return head;   //给出终止条件
        }
        else{
            new_head = reverseList(head->next);
            head->next->next = head;   
            head->next = nullptr;   //每一步都是head在变化
            return new_head;
        }
    }
};

注意点

  1. 递归的思想以及操作放置的位置还是要掌握好;

参考资料:

  1. 如何递归反转链表
  2. 剑指 Offer 24

问题12:复杂链表的复制

问题描述:请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
问题要求:无
解题思路:这道题主要是参考其他人的思路(很妙)。
首先复制一次:把a->b->c变成a->a’->b->b’->c->c’
这样相当于把链表的next这一属性定下来了(复制了a.b.c的顺序);
然后根据a.b.c的random属性,赋值a’.b’.c’的random属性;
最后把a’.b’.c’独立出来。
代码

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (head == nullptr){
            return nullptr;
        }
        for (Node* node = head;node != nullptr;node = node->next->next) {
            Node* newNode = new Node(node->val);
            newNode->next = node->next;
            node->next = newNode;
        }
        for (Node* node = head;node != nullptr;node = node->next->next) {
            if(node->random != nullptr) {
                Node* newNode = node->next;
                newNode->random = node->random->next;
            }                   
        }
        Node* new_head = head->next;
        for (Node* node = head;node != nullptr;node = node->next) {
            Node* newNode = node->next;
            node->next = node->next->next;
            newNode->next = (newNode->next != nullptr)? newNode->next->next:nullptr;              
        }
        
        return new_head;

    }
};

注意点

  1. 这是个很有趣的思路,可以参考。

参考资料:

  1. 剑指 Offer 35
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值