五月集训(第13天)—双向链表
双向链表
1. 1472. 设计浏览器历史记录
思路:
设置一个双向链表,按题意模拟即可。注意访问一个新网页时要把之前的next
网页结点删除。
struct NODE {
string val;
NODE *pre;
NODE *next;
};
class BrowserHistory {
NODE *head, *List; /* head是指针,List是链表,用head访问遍历List */
public:
BrowserHistory(string homepage) {
List = new NODE();
List->pre = List->next = NULL;
List->val = homepage;
head = List;
}
void visit(string url) {
NODE *Next_page = head->next;
// 删除浏览过的next网页,再访问 url
NODE *temp = Next_page;
while (Next_page) {
temp = Next_page->next;
delete Next_page;
Next_page = temp;
}
// 创建新的结点保存url信息,并将结点加入列表
Next_page = new NODE();
Next_page->val = url;
Next_page->next = NULL;
Next_page->pre = head;
head->next = Next_page;
head = head->next;
}
string back(int steps) {
while (head->pre && steps) {
steps--;
head = head->pre;
}
return head->val;
}
string forward(int steps) {
while (head->next && steps) {
steps--;
head = head->next;
}
return head->val;
}
};
/**
* Your BrowserHistory object will be instantiated and called as such:
* BrowserHistory* obj = new BrowserHistory(homepage);
* obj->visit(url);
* string param_2 = obj->back(steps);
* string param_3 = obj->forward(steps);
*/
2. 430. 扁平化多级双向链表
思路:
把每次访问->child
的结点视为进入更深的一层,用depth
记录访问深度,用Node *history_curr_next[]
记录每次访问更深深度时,先记录当前结点的下一个结点,方便返回。类似深度搜索,一路搜进去,搜到头了回来,继续往后搜。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
};
*/
class Solution {
public:
Node* flatten(Node* head) {
Node *ret = head;
Node *history_curr_next[1005];
int depth = 0;
Node *new_temp = NULL;
while (head) {
if (head->child != NULL) {
history_curr_next[++depth] = head->next;
new_temp = head->child;
head->next= new_temp;
new_temp->prev = head;
head->child = NULL;
}
if (head->next == NULL && depth > 0) {
while (depth > 0 && history_curr_next[depth] == NULL) {
if (history_curr_next[depth] != NULL) break;
else depth--;
}
head->next = history_curr_next[depth];
if (history_curr_next[depth] != NULL)
history_curr_next[depth--]->prev = head;
}
head = head->next;
}
return ret;
}
};
3. 剑指 Offer II 028. 展平多级双向链表
思路:
和第二题不能说是相似,只能说是一模一样。
// code同第二题
4. 剑指 Offer 36. 二叉搜索树与双向链表
思路:
递归遍历二叉树,大问题拆分成小问题,分别将左右子树变成双向链表,然后将左链表 <-> root <-> 右链表
。
每个递归过程会将一颗子树变为一个双向链表,并返回其两端的结点。递归出口为叶节点返回即可。
最后首尾相连(注意:首尾相连时需要特判链表为空的情况)。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {}
Node(int _val) {
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
public:
void dfs(Node *root, Node **minNode, Node **maxNode) {
if (root == NULL) {
*minNode = NULL;
*maxNode = NULL;
return ;
}
Node *lminNode, *lmaxNode, *rminNode, *rmaxNode;
if (root->left) { /* 拼接左子树 */
dfs(root->left, &lminNode, &lmaxNode); /* 将root的左子树转化为双向链表 */
lmaxNode->right = root;
root->left = lmaxNode;
*minNode = lminNode;
} else {
*minNode = root;
}
if (root->right) { /* 拼接右子树 */
dfs(root->right, &rminNode, &rmaxNode); /* 将root的右子树转化为双向链表 */
rminNode->left = root;
root->right = rminNode;
*maxNode = rmaxNode;
} else {
*maxNode = root;
}
}
Node* treeToDoublyList(Node* root) {
Node *minNode = NULL;
Node *maxNode = NULL;
dfs(root, &minNode, &maxNode); /* 将二叉搜索树转化为双链表 */
// 首尾相连
if (minNode != NULL) {
minNode->left = maxNode;
maxNode->right = minNode;
}
return minNode;
}
};
东方欲晓,莫道君行早。