我们前几天已经学过了线性表:顺序表,链表和栈,但是只有理论知识是绝对不够的,我给大家找了一些很经典的题目,一定要做到立马有思路哦
(如果还有小可爱没有看过我的顺序表,链表和栈的知识点说明,请看↓
)
另外前一篇练习文章在下面,一定要把前一篇文章好好弄懂再看着一篇哦
目录
由于链表的知识很多,相关的好题更多,所以本文选取典中典的好题给大家把常见思路都见一见,并不能说包含所有但是学完肯定能应付很多题目
我们开始吧~~
1.链表
1.1翻转链表
其实完全不用遍历到最后一个节点,把最后的换成新头然后往前走
因为我们在之前在单链表学过,单链表的结构决定了他就是不能很好的“倒车”,非常麻烦,还需要考虑指向的问题
有点小伙伴说那就弄成双向,是一个办法,但是人家给你一个单链表你非要硬做成双向...
最好的方法
从第一个链表经过我们的操作变成了下面这个
之后把tail(此时在NULL)变成cur,cur变成next保存的节点就可以了
(注意:这里tail一开始初始化成NULL并没有开辟空间所以空间复杂度还是O(1))
struct ListNode* reverseList(struct ListNode* head){
struct ListNode*tail=NULL,*cur=head,*next=head;
while(cur)
{
next=cur->next;
cur->next=tail;
tail=cur;
cur=next;
}
return tail;
}
1.2 寻找中间节点
这个看起来是不是立马想到:分奇数偶数!!先把链表遍历然后记录节点个数返回个数/2的节点!!!
struct ListNode* middleNode(struct ListNode* head){
struct ListNode*tail=head;
int count=0;
while(tail)
{
count++;
tail=tail->next;
}
for(int i=0;i<count/2;i++)
{
head=head->next;
}
return head;
}
这样做肯定可以啊,也很简洁
但是我们不能局限于写出来和我只能想到...
更优化的办法:快慢指针
快指针一次走两步,慢指针一次走一步,这样听起来好玄乎,举个例子看看
发现所有可能出现的情况都包含在内,如果本身链表为空,那slow自然就是NULL返回也直接是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;
}
1.3返回倒数第n个节点
根据上一个题目的思路,只需要每次fast先走k个,如果在走的过程中有fast==NULL,那么直接返回NULL,然后再fast和slow各走一步就可以了
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
int count=0;
struct ListNode*slow=pListHead,*fast=pListHead;
while(k--)
{
if(fast)
{
fast=fast->next;
}
else
{
return NULL;
}
}
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
考虑到吸收效率的情况,今天还是只放三个题目,记得关注继续看下文哦~~