首先链表的定义里内存空间不连续,节点通过指针指向下一地址。链表适合增删改,访问的时间复杂度较高o(n),特性与数组相反。
手写单向链表节点定义如下,每个节点包括元素和指向下个节点指针两部分。
typedef struct ListNode{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}//构造函数便于初始化
} ListNode;
203.移除链表元素
题目输入一个链表的头节点和一个值,要求返回删除这个值的链表节点。
由于不同节点是通过指针相连接的,所以要删除节点正常只需要把前一个节点的指针指向下一个节点就可以,但是头节点没有前一个节点,所以虚拟头节点的作用就来力。
先创建虚拟头节点dummyhead:初始化并把指针指向head节点。利用临时节点指针cur遍历,找到目标值就执行删除操作,改指针指向。
注意事项:
1.遍历链表的写法while(cur->next!=NULL){ cur=cur->next };
2.删除链表的时候不能直接改指针指向,中间删除部分需要先存到tmp里再delete,否则会造成内存泄漏;
3.cur是指向dummyhead的结构体类型的指针,起到遍历作用;
4.不能直接return head因为有可能原头节点被删除,所以要先利用dummyhead介入;
707.设计链表
挺哈人的一道题,考察各种链表基本操作:
0.链表定义
1.获取第n个节点的值(输入索引返回值
2.头部插入节点
3.尾部插入节点
4.第n个节点前插入节点
5.删第n个节点
链表定义不多说,元素和指针还有构造函数必须掌握。
初始化链表:
获取第n个值:
这里的遍历方式也是用cur指针,不过起始位置不同于上题。时间关系这里就偷别人的代码(这题好像手撕频率不高偷个懒
头部插入节点:
后面几种也是同理的,关键都是要会创建新节点、会用while遍历链表。
这题用来回顾链表基础操作是很好的,不过代码也太长而且没考察算法面试可能性应该小,标记一下以后二刷,别为此消磨了耐心。。。
206.反转链表
这题面试频率很高!需要重点掌握!
看眼题目
很好理解。解法有双指针和递归,递归我太菜了学不懂,用双指针解
说是双指针其实是三指针,cur、pre、next分别记,只有前两者的话当前节点反转后下一个节点没办法保存,所以三指针是必要的。创建三个指针pre、cur、next并注意初始化,执行循环:next指向pre,pre和cur指针向右移动,最后返回的是头节点也就是pre
我发现思路混乱的原因总是把=理解后者赋值给前者,其实链表里的next就可以直接视作指向箭头,把pre=cur视作指针的移动,代码就好理解很多,可以想象一下三行代码分别对应三个指针next、pre、cur按次序移动的画面,第二行执行对应着箭头换向。
今日总结
虚拟头节点dummyhead和临时指针cur方法必须掌握,链表经常考察。创建新节点、创建指针、while遍历链表的写法是一定要会的,反转链表重中之重