链表分割(牛客较难)+环形链表(leetcode简单)

今天还是更新两个关于链表的题

第一个

题目描述:

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

思路:

1.这个题的总体思路就是定义两个带哨兵位的链表,比x大的放到一个链表中,比x小的放到一个链表中,也就是将原链表分割给这两个新定义得到的链表,最后合起来。

2.这种题其实还有一个规律,其实这个题使用尾插来做就是最简单的,而尾插往往就需要定义哨兵位来解决,这样的话比较简单,关于这个问题,其实我之前写过一篇返回倒数第k节点的文章,里面如果定义了哨兵位的话,可以省去不少的麻烦,比如判空

合并两个有序链表(leetcode简单)+链表中倒数第k个结点_何以过春秋的博客-CSDN博客

3.这里就是一步步尾插,但要注意有极端情况的发生,就是可能形成环,比如给链表 3 4 5 7 1 2,给x为6,那么最后输出应该是3 4 5 1 2 7 ,这里问题就来了,7的next其实还是指向1,那么这里就会形成环,所以必须对它进行置空

4.最后只要将哨兵位释放掉就行,释放前记得保存头节点,以免找不到。

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        //定义两个哨兵位的头节点
        struct ListNode*greaterhead,*greatertail,*lesshead,*lesstail;
        greaterhead=greatertail=(struct ListNode *)malloc(sizeof(struct ListNode));
        lesshead=lesstail=(struct ListNode *)malloc(sizeof(struct ListNode));
        
        //置空
        greatertail->next=NULL;
        lesstail->next=NULL;
        
        struct ListNode*cur=pHead;
        while(cur)
        {
            if(cur->val<x)
            {
                lesstail->next=cur;
                lesstail=lesstail->next;                  
            }
            else
            {
                greatertail->next=cur;
                greatertail=greatertail->next;
            }
            cur=cur->next; 
        }
        lesstail->next=greaterhead->next;
        //这里考虑极端情况,否则可能形成环
        greatertail->next=NULL;
        //将两个哨兵位的头节点释放掉,但要提前定义一个节点,也就是哨兵位的next,最后做返回用。
        struct ListNode*head=lesshead->next;
        free(greaterhead);
        free(lesshead);
        return head;
    }
};

 第二个

141. 环形链表

思路:其实这个题以前经常考


1.这个题首先必须想明白,不能遍历整个链表!

2.使用快慢指针来做,这里其实还有一个非常经典的面试问题,那就是如果有环,为什么fast和slow一定能碰上?

证明:假设slow入环时,fast和slow的距离已经差了N步,接下来两者走一次,相差N-1步,接下来两者走一次,相差N-2步,也就他们之间的距离每次缩小1,走N步,距离变为零,也就是相遇了。

再想想,如果fast一次走3步,走4步呢?是不是还一定能追上?’

不一定了,道理同上。

bool hasCycle(struct ListNode *head) {
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        return true;
    }
    return false;
    
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何以过春秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值