7.17 链表中等 430 61 24 92

430 扁平化多级双向链表

在这里插入图片描述

思路
1. 题目:Node 需处理 prev next child
2. 大体:遍历链表;判断节点是否有child节点;
有,存储temp->next,令ch = temp->child,处理当前节点temp->child指向nullptr,temp->next = ch,ch->prev = temp,
然后再遍历子链表新建指针childTail指向其中最后一个节点,
然后处理temp原next next->prev = childTail,childTail->next = next;【思路√但代码原逻辑混乱】
3. 细节:因增插节点,所以dummy;new_head->prev =nullptr;

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* prev;
    Node* next;
    Node* child;
};
*/

class Solution {
public:
    Node* flatten(Node* head) {
        //双链表,增加节点,虚拟头部
        Node* dummy = new Node(0);
        dummy->next = head;
        Node* temp = dummy;

        while(temp){
            if(temp->child){
                Node* ch = temp->child;
                Node* next = temp->next;

                temp->next = ch;
                ch->prev = temp;
                temp->child = nullptr;
                //需要新建
                Node* chTail = ch;
                while(chTail->next){//ch指向最后一个结点
                    chTail = chTail->next;
                }
                
                if(next){
                    chTail->next = next;
                    next->prev =chTail;
                }
            }
            temp = temp->next;
        }

        Node* new_head = dummy->next;
        if (new_head) {
            new_head->prev = nullptr; // 将新头节点的prev设置为null
        }
        delete dummy;
        return new_head;

    }
};

61 旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
思路
1. 题目:右移k个位置
2. 大体:(k>len)确定真实移动节点数,判定head的长度,计算k = k % len;将头尾相接;判定新尾部,newTail = head,循环len-k-1次,将尾部断开,并保存新的头部newHead = newtail->next;【思路√但代码原逻辑混乱】
3. 细节:k % len == 0 或者 k == 0 或者head为空


class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head || k == 0 ) return head;

        //链表长度
        ListNode* cur = head;
        int len = 1;
        while(cur->next){
            cur = cur->next;
            len++;
        }

        //实际移动步数
        k = k % len;
        if(k == 0){return head;}

        //循环链表,头尾相接
        cur->next = head;

        //找到新尾部
        int n = len - k;
        ListNode* newTail = head;
        for(int i = 1 ; i < n ; i++){
            newTail = newTail->next;
        }

        //断开循环
        ListNode* newHead = newTail->next;
        newTail->next = nullptr;

        return newHead;

    }
};

24 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路
1. 题目:两两交换 节点
2. 大体:遍历链表;保存指针的next和nextnext,进行节点交换;移动指针至新交换的第二个节点即原next上,继续循环。【思路√代码细节还是有问题】
3. 细节:while循环保证next和nextnext都存在,当head的长度为0or1即if(!head || !head->next)return head;因增删改节点,所以dummy。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(!head || !head->next)return head;

        ListNode* dum = new ListNode(0);
        dum->next = head;
        ListNode* cur = dum;
        while(cur){
            ListNode* N = cur->next;
            ListNode* newN = N->next;
            if(newN){
                cur->next = newN;//更新尾部
                N->next = newN->next;
                newN->next = N;
                cur = N;
            }else{
                break;
            }
        }

        ListNode* newHead = dum->next;
        delete dum;
        return newHead;
    }
};

修改:可以将条件语句融到while循环的判断中

Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(!head || !head->next) return head;

        ListNode* dum = new ListNode(0);
        dum->next = head;
        ListNode* cur = dum;
        while(cur->next && cur->next->next){
            ListNode* first = cur->next;
            ListNode* second = cur->next->next;

            //交换节点
            first->next = second->next;
            cur->next = second;
            second->next = first;

            //移动指针
            cur = first;
        }

        ListNode* newHead = dum->next;
        delete dum;
        return newHead;
    }
};

92 反转链表Ⅱ

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
思路
1. 题目:left <= right;反转从位置 left 到位置 right 的链表节点
2. 大体:移动到要反转节点的前一个;翻转;链接已翻转部分p和未反转部分cur【出错部分,只链接p没有链接cur】。
3. 细节:left == right || !head return head;对head的第一个节点会影响,dummy


class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(left==right || !head->next)return head;

        ListNode* dum =new ListNode(0);
        dum->next = head;
        ListNode* prev = dum;

        //移动到边界处,prev用于保存颠倒部分前的内容
        for(int i = 1 ; i < left ; i++){
            prev = prev->next;
        }

        //颠倒链表
        ListNode* p = nullptr;
        ListNode* latt = nullptr;
        ListNode* cur = prev->next;
        for(int i = left ; i <=right;i++){
            latt = cur->next;
            cur->next = p;
            p = cur;
            cur = latt;
        }

        //cur为为反转的部分 p为翻转的部分
        prev->next->next = cur;
        prev->next = p;
        

        ListNode* newHead = dum->next;
        delete dum;
        return newHead;



    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值