五月集训(第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; 
    }
};
posted @ 2022-05-14 15:07  番茄元  阅读(33)  评论(0)    收藏  举报