空间复杂度OJ

返回倒数第K个节点

. - 力扣(LeetCode)

思路:创建快慢指针分别指向头节点,让快指针先走k步使快慢指针保持k个距离,走完在让快慢指针一起走,当快指针走到空,慢指针当前位置就是倒数第k个节点。

struct ListNode* fast = head,*slow = head;
//快指针先走k步 让快慢指针保持k个距离
while(k--)
{
    fast = fast->next;
}
//如果给的是无效的k,就要判断一下
if(fast)
return NULL;
//快慢指针一起走
while(fast)
{
    fast = fast->next;
    slow = slow->next;
}
//将找到的倒数k节点的值返回
return slow->val;

 链表的回文结构

链表的回文结构_牛客题霸_牛客网

  •  回文的概念:从中间切开俩边对称就是回文。
  • 思路:找到中间节点,从中间节点开始后面逆置,头节点和中间节点依次往后判断是否相等,走到尾就是回文,不然就不是回文。
  • 找中间节点的两种情况:奇数个数只有一个中间节点,偶数个数有俩个中间节点,返回第二个中间节点。
  • 奇数个数比较时不要被表象迷惑最后一个数没数比,中间节点前一个数指向的就是最后一个要比较的数,所以是它自己和自己比。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
//找中间节点
struct ListNode * middlenode(struct ListNode *head)
{
    struct ListNode *fast = head,*slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
//逆置
struct ListNode *reverseList(struct ListNode *head)
{
    struct ListNode *cur = head;
    struct ListNode *newhead = NULL;
    while(cur)
    {
        struct ListNode *next = cur->next;
        cur->next = newhead;
        newhead = cur;
        cur = next;
    }
    return newhead;
}
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        struct ListNode *mid = middlenode(A);
        struct ListNode *rmid = reverseList(mid);
        while(A && rmid)          //头节点或中间节点有一个为空就结束
        {
            if(A->val != rmid->val) //判断A的值和rmid的值是否相等 不相等返回假
            return false;
            A = A->next;
            rmid = rmid->next;
        }
        return true;               
    }
};

相交链表

. - 力扣(LeetCode)
  • 注: 因为单链表只能指向一个下一个地址所以相交不存在X型只能是Y型。
  • 判断是否相交(判断尾指针,注意需要用地址判断),若相交找出第一个交点。
  • 思路1:A链表的节点依次跟B链表所有节点比较,A某个节点跟B链某个节点相等,这个节点就是交点,时间复杂度O(N^2)。
  • 思路2:先将A、B各链表走到尾节点判断地址是否相等,不相等即为不相交返回空,相等即为相交,再求出A、B链表长度,让长链表先走出差距步,在同时走第一个相等就是开始相交的位置,时间复杂度为O(N)。
  • O(3*N)
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    //创建俩个结构体指针分别保存俩个链表的头节点,防止原有节点位置被改变
        struct ListNode *curA = headA,*curB = headB; 
    //创建俩个变量保存俩个链表的长度,因为最后一个节点的NEXT为空进不去循环无法++少计算一个,所以初始 
    //化为1
        int lenA = 1,lenB = 1;   
        while(curA->next)        //让A链表一直走,走到节点的NEXT指向空结束求出长度。
        {                          
            curA = curA->next;    
            ++lenA;
        }
        while(curB->next)        //让B链表一直走,走到节点的NEXT指向空结束求出长度。
        {
            curB = curB->next;
            ++lenB;
        }
        if(curA != curB)         //此时A、B链表都走到最后如果不相等即不相交 返回NULL
        {
            return NULL;
        }
    //假设法 
        int gap = abs(lenA - lenB);//求出A和B的绝对值
        struct ListNode *longList = headA,*shortList = headB;//假设A长、B短
        if(lenB >lenA)//判断B如果比A长将B赋给长变量、A赋给短变量
        {
            longList = headB;
            shortList = headA;
        } 
    //长的先走差距步
        while(gap--)
        {
            longList = longList->next;
        }
    //同时走,第一个相等就是交点
        while(longList != shortList)
        {
            longList = longList->next;
            shortList = shortList->next;
        }
        return longList;
    }

随机链表的复制 

           

/*
解题思路:
此题可以分三步进行:
1.拷贝链表的每一个节点,拷贝的节点先链接到被拷贝节点的后面

2.复制随机指针的链接:拷贝节点的随机指针指向被拷贝节点随机指针的下一个位置

3.拆解链表,把拷贝的链表从原链表中拆解出来

*/

class Solution {
public:
    Node* copyRandomList(Node* head) {
        // 1.拷贝链表,并插入到原节点的后面
        Node* cur = head;
        while(cur)
        {
            Node* next = cur->next;

            Node* copy = (Node*)malloc(sizeof(Node));
            copy->val = cur->val;

            // 插入
            cur->next = copy;
            copy->next = next;

            // 迭代往下走
            cur = next;
        }

        // 2.置拷贝节点的random
        cur = head;
        while(cur)
        {
            Node* copy = cur->next;
            if(cur->random != NULL)
                copy->random = cur->random->next;
            else
                copy->random = NULL;

            cur = copy->next;
        }

        // 3.解拷贝节点,链接拷贝节点
        Node* copyHead = NULL, *copyTail = NULL;
        cur = head;
        while(cur)
        {
            Node* copy = cur->next;
            Node* next = copy->next;

            // copy解下来尾插
            if(copyTail == NULL)
            {
                copyHead = copyTail = copy;
            }
            else
            {   
                copyTail->next = copy;
                copyTail = copy;
            }

            cur->next = next;

            cur = next;
        }

        return copyHead;
    }
};

            

  • 42
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值