1024狂欢力扣经典链表OJ题合集
Posted 东条希尔薇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1024狂欢力扣经典链表OJ题合集相关的知识,希望对你有一定的参考价值。
现在的力扣题的源代码我会全部一并上传至我的码云仓库里面,点我看仓库
写在前面
首先祝各位程序猿1024狂欢节快乐鸭!这是属于我们的节日
为了致敬1024,今天的力扣系列不再是一题了,而是多个题的组合
也是与我们最近更新的内容梦幻联动
206题:反转链表
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
例如:
1->2->3->4->5
我们要返回5->4->3->2->1
思路求解
此题我们有两个方法求解
指针反转法
设我们有这个链表
我们可以想到,要反转链表,我们可以尝试去反转指针的指向
一个一个的反转,直到反转到末尾就行了
说起简单,我们其实要考虑很多细节
- 题目说的是单链表,我们不能直接找到前面的结点,所以需要一个指针指向当前指针的前面结点
- 改变指向后,我们无法找到后面的结点了,所以还需要另外一个指针指向当前指针后面的结点
所以这里我们需要三个指针,prev,cur,next
初始化:
prev先指向空,cur指向head,next指向head->next
遍历方法图解:
结束条件,cur为空时,但要注意,cur为空时,不能移动next了,因为这会导致空指针解引用的错误,具体在代码中说明
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
if(!head)
return NULL;//这里是空链表的情况
struct ListNode* prev=NULL,*cur=head,*next=head->next;
while(cur)
{
cur->next=prev;
prev=cur;
cur=next;
if(next)
next=next->next;//这里是判断cur是否走向末尾,走向末尾就不能移动next了
}
return n1;
}
头插法
我们可以重新定义一个链表出来
我们从头遍历链表,并把结点头插至新链表中
画图求解
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
if(!head)
return NULL;
struct ListNode* newhead=NULL,*cur=head,*next=head->next;
while(cur)
{
cur->next=newhead;
newhead=cur;
cur=next;
if(next)
{
next=cur->next;
}
}
return newhead;
}
876题 链表的中间结点
题目描述
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
思路求解:
这是一个比较典型的快慢指针的问题,虽然思路比较简单,但是真的不容易想到啊(默默流泪)
我们知道,一个中点在数学上什么特征?
上图,我们显然有2AC=AB
所以我们也利用了中点的特性
定义两个指针fast和slow,其中fast每次走两步,slow每次走一步
当fast走向末尾或者走向倒数第一个结点时,slow所指向的位置就是中点
黄色标记的是为什么呢?
因为我们有链表长度为奇数和偶数的情况
同样,我们画图求解
这是偶数个结点的情况
这是奇数个结点的情况
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
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;
}
剑指offer 22.链表倒数第K个结点
题目描述
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
思路求解
因为单链表只能顺着走,无法倒着走
所以我们顺着这个思路思考,我们也同样正着走
这也是一个双指针问题
跟上一个题有异曲同工之妙
我们可以先让fast指针先走k步,这样的目的是保证fast和slow相差k个距离
fast走完k步后,slow和fast同时走
结束条件:fast走向链表的末尾
图解
代码实现
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
*
* @param pListHead ListNode类
* @param k int整型
* @return ListNode类
*/
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
struct ListNode* fast=pListHead,*slow=pListHead;
while(k--)
{
if(!fast)
{
return NULL;
}
fast=fast->next;
}
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
21 合并两个有序链表
题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
思路求解
这个跟数组的合并思路差不多,我在这篇博客中讲到过
思路就是定义两个指针分别指向两个链表,然后比较大小,谁小就尾插进我们定义的新链表中。
结束条件是l1,l2其中一个指针指向空,然后直接链接剩下的结点即可
在这里,为了防止新链表为空带来的种种问题,我们在这里引入一个哨兵位头结点
画图求解
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(!l1)
return l2;
if(!l2)
return l1;
//上面是其实一个链表为空的情况
struct ListNode* head=malloc(sizeof(struct ListNode));//开设头结点
struct ListNode* tail=head;//为尾插定义的
while(l1&&l2)
{
if(l1->val<l2->val)
{
tail->next=l1;
l1=l1->next;
tail=tail->next;
}
else
{
tail->next=l2;
l2=l2->next;
tail=tail->next;
}
}
if(!l1)
{
tail->next=l2;
}
if(!l2)
{
tail->next=l1;
}//链接剩余的元素
struct ListNode* newhead=head->next;
free(head);
return newhead;
}
点我直通1024小调查嘻嘻嘻
以上是关于1024狂欢力扣经典链表OJ题合集的主要内容,如果未能解决你的问题,请参考以下文章
Chain Surfase Test - java 链表经典 OJ 面试题 - 巨细