剑指Offer刷题记录_day2

剑指Offer刷题记录_day2

Day 2: 链表

Q1 :Reserve单链表

解题思路:

  1. 正向遍历,反向填充数组

  2. 类比后续遍历,利用递归,先遍历置尾节点,再向数组内插入

  3. 直接调用反转方法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
//方法一:
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {

        ListNode *node = head;
        int len = 0;
        while(node){
            len++;
            node = node->next;
        } 
        vector<int> L(len);
        node = head;
        while(node){
            L[len-1] =node->val;
            len--;
            node = node->next; 
        }
        return L;
    }
};
//方法2:反转
public:
    vector<int> reversePrint(ListNode* head) 
    {
        vector<int> res;

        while(head)
        {
            res.push_back(head->val);
            head=head->next;
        }

        reverse(res.begin(),res.end());

        return res;
    }
//方法三:递归
public:
    // 使用递归,也就是后序遍历的思路,直到走到链表尾部时才回溯打印节点
    vector<int> res;
    vector<int> reversePrint(ListNode* head) {
        helper(head);
        return res;
    }

    void helper(ListNode* head)
    {
        if(!head)return;
        helper(head->next);
        res.push_back(head->val);
    }

Q2 逆转单链表输出单链表

解题思路:

  1. 双指针灵活运用 pre p temp
  2. 递归运用

解题代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
// 双指针
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        
        ListNode *pre = nullptr , *p = head ;
        ListNode *temp;
        while(p!=nullptr)
        {
            temp = p->next;
            p->next = pre;
            pre = p;
            p = temp;
        }
        return pre;

    }
};
//递归
ListNode* reverseList(ListNode* head) {
        
        if(head == NULL || head->next == NULL) { 
            return head;
        }
        ListNode *node = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return node;

    }

Q3 复制复杂的链表

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

考察点: 链表不是简单的线性的关系,简单的正向遍历只能构造链表的前后关系。而本题的节点之间还存在一个random的指针域,因此不能用简单的遍历实现,必须采用某种方法来找到某一结点的random结点。容易想到的是用哈希表构造原链表节点新链表对应节点 的对应关系,不容易想到使用拼接链表的方法。

方法:

  • 先一次遍历将链表构造出来,再依次修改random指针域 (显然在查找random节点时,效率较低)。
  • 构造哈希表,对于已经构造好的hash表查找结点的时间复杂度为O(1);考虑构建 原链表节点新链表对应节点 的键值对映射关系,再遍历构建新链表各节点的 nextrandom 引用指向即可。
  • 拼接链表,将新的复制结点插入到旧结点之后,此时新结点的random域可以表示为 p->next->random = p->random->next,构造完新结点之间的关系后,将新链表拆分;
#方法二
/*
// 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;
        Node* p = head;
        unordered_map <Node*, Node*> hash;
        while(p != nullptr)
        {
            hash[p] = new Node(p->val);
            p = p->next;
        }
        p = head;
        while(p != nullptr)
        {
            hash[p]->next = hash[p->next];
            hash[p]->random = hash[p->random];
            p = p->next;
        }
        
        return hash[head];
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值