剑指Offer刷题记录_day2
Day 2: 链表
Q1 :Reserve单链表
解题思路:
-
正向遍历,反向填充数组
-
类比后续遍历,利用递归,先遍历置尾节点,再向数组内插入
-
直接调用反转方法
/**
* 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 逆转单链表输出单链表
解题思路:
- 双指针灵活运用 pre p temp
- 递归运用
解题代码
/**
* 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);考虑构建 原链表节点 和 新链表对应节点 的键值对映射关系,再遍历构建新链表各节点的
next
和random
引用指向即可。 - 拼接链表,将新的复制结点插入到旧结点之后,此时新结点的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];
}
};