目录
2. 单链表中不给头指针能不能在Pos位置前面插入一个节点?
1.断言的好处
断言可以减少调试成本,检查那些明显的错误。比如说在单链表中由于第一次插入要修改头指针的地址所以要传参二级指针,这个二级指针指向头指针,当为单链表的时候*pphead可能为空,但是无论在什么情况下pphead也就是存放头指针地址的指针,不可能为空。这时候就可以断言,防止别人在使用你的函数的时候错误传参。
当单链表删除的时候要断言*pphead不为空,因为为空了怎么删除下一个节点?
2. 单链表中不给头指针能不能在Pos位置前面插入一个节点?
按正常的插入要求来说是不可以的,没有头指针的话只能从pos之后插入,不能从pos之前插入,因为前面插入需要找到pos的前一个节点,在单链表中需要遍历,没有头指针就没有遍历的开始条件。
但是如果你在pos之后插入,把插入的newnode节点内的值和pos的节点的值交换,逻辑上也勉强算是在pos之前插入。
3.这里传一级指针 为什么还能该变头节点的指向
因为这里返回了头指针,可以用main函数里面的头指针接收,在这个函数执行完了之后并没有改变指向,而是main函数里面将函数返回值赋值给头节点才改变指向。
自己写的传一级指针返回头节点的地址也可以,只不过这样写麻烦不简洁。
5.循环
while(k--)
{
}
走了k次
while(--k)
{
}
走了k-1次
7.关于free
free是把一块内存空间的使用权还给操作系统,free并不改变原来指向这块地址的指针,但是如果这个指针还对这块内存进行解引用操作的话就会导致非法访问
8.力扣 反转链表
先画图,不要嫌画图麻烦,画图5~10分钟,写代码10分钟。如果不画图30分钟不一定写一道题。
方法一:三指针,双指针这里不够用,由于cur的next一旦指向prev,就找不到了cur的后一个节点,所以用一个指针next记录cur的后一个节点。
最后要return prev 还有循环终止条件都是画图得来的。
方法二:用指针数组来记录每个节点的地址,然后交换这个数组里面的地址的val值。
方法3:头插法,头插法可以逆序链表,先把新头设置为空,然后让cur指向新头,然后再更改新头的位置,注意要提前保存cur->next的地址,因为cur指向新头后它的next就找不到了。
9.力扣 合并两个有序链表
思路是先找到头(头是俩链表的值小的那个),然后遍历链表(找到头的那个从头后面开始遍历,不是头的从头开始遍历)进行链接直到一方为空,然后再把不为空的剩余的链表链接到cur后面就行了。
尾插,要有一个变量来记录尾巴,这里为cur
10.力扣 链表的中间节点
快慢指针:
可以二倍快慢,也可以快指针提前走一段距离
11.力扣 移除链表元素
12.链表中倒数第k个结点_牛客题霸_牛客网
方法1:倒数第k个就是正数第L-k+1个也就是下标为L-k的那个
第二种方法:让快指针先走k步
这种方法有很多需要额外判断的条件。
13.链表分割_牛客题霸_牛客网
这个题第一遍做用的是自己的笨方法:消耗比较多
思路是先把链表的数存入数组里面,然后在对数组进行操作,让数组的大于等于X排在后面,小于X排在前面,最后再把数组赋值给链表的val
思路二:
由于要求不改变顺序只能尾插。
大于等于x尾插到带哨兵位的头节点greater
小于x的尾插到带哨兵位的头节点lower
最后再把小的尾部链接到大的哨兵位的next
大的链表的尾的next置空,防止链表成环
返回小的哨兵的next
为什么要带哨兵位?
因为哨兵位可以不用处理链表为空的情况,比如说全部比x小或者全部比x大的情况的时候两个链表中的某个链表为空,如果没有哨兵位的话,两个链表的链接就会出问题。
需要注意的是这里要考虑链表带环的问题就是最大的那一个在链接完两个链表了之后仍然指向之前的next所以要把greatTail->next设置为空
14.链表的回文结构_牛客题霸_牛客网
回文:123 321是回文
发现回文的逆置还等于它本身。
就可以先逆置一个然后再比较
但是你一但逆置修改的是原链表,原链表就不在了。无法让原链表和逆置的链表进行比较。所以逆置这个方法不行。(除非你先把原链表复制,然后拿这个复制的和逆序的链表比较)
在牛客上能跑过,这是因为牛客的测试用例少,在力扣上就跑不过
下面是正确的题解
15.力扣 相交链表
这个思路没想到,老师点播思路后自己写出来了
就是变量A B两个链表求他们的长度,然后让长的先走长度差步,然后一块走,一块走的时候判断指针相等的时候就返回,到最后也没返回就返回NULL
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) { struct ListNode *curA=headA; struct ListNode *curB=headB; int La=0; int Lb=0; while(curA) { La++; curA=curA->next; } while(curB) { Lb++; curB=curB->next; } curA=headA; curB=headB; int k=La>=Lb?(La-Lb):(Lb-La); if(La>=Lb) { while(k--) { curA=curA->next; } while(curA&&curB) { if(curA==curB) { return curA; } curA=curA->next; curB=curB->next; } } else { while(k--) { curB=curB->next; } while(curA&&curB) { if(curA==curB) { return curA; } curA=curA->next; curB=curB->next; } } return NULL; }
abs
取绝对值
16.力扣 环形链表
带环链表可不敢遍历,死循环。
思路是快慢指针,并且只能是两倍速度。当慢指针进入环中的时候就变成了快指针追慢指针的追击问题了,每次距离缩短一个字节一定能追上。当速度为其他倍数的时候一定追不上。
记住:只要有环+速度设置为两倍就一定会相遇。没环的话while循环一定会退出(fast走到NULL或者最后节点),有环的话一定会追上。