专题:链表
题目:移除链表元素
题意:删除链表中等于给定值 val 的所有节点。
示例 :
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
解题思想:
我们为了统一操作,我们给链表添加一个虚拟头结点dummyhead,这样就统一了处理头结点head就和处理其他的节点方式。让指针指向虚拟头结点,然后从前往后遍历链表,遇到val值相等的元素,就直接把它移除了。
细节注意:
因为我们是删除节点,所以创建的cur指针,指向的是dummyhead,而不是dummyhead->next; 还有分清楚dummyhead->next = head的含义 和 head = dummyhead->next的含义;
dummyhead->next = head;指的是虚拟头结点的next指向head。此时head是确定的位置。dummyhead->next 不确定的指针(创建虚拟头结点是使用)。 而 head = dummyhead->next;指的是让head指针指向dummyhead->next;此时的head是不确定的。而dummyhead->next是确定的(最后完成链表的创建之后,将新链表赋给head)。总的来说,就是让左边不确定的指针,指向右边确定的指针。或者可以理解为,把右边确定的指针赋值给左边不确定的指针。
代码实现:
题目:设计链表
解题思想:
首先是一个类,里面包含了链表结点(包含 数值val,结点指针next,结点构造函数),类的私有成员变量(虚拟头结点指针dummyhead,结点数目size)然后具体的方法有,初始化链表。得到第index个元素,头插,尾插,头删,尾删,在第index个位置插入,在第index个位置删除。
细节注意:
方法里面基本都用到了虚拟头结点,如果涉及到删除,添加元素。那我们在初始化指针cur的时候,我们都是让cur指向dummyhead(因为删除,添加都需要在它的前一个位置,对下一个位置的元素进行操作);如果只是得到某个位置的元素,不涉及添加,删除时,我们在初始化cur时,让他指向 dummyhead->next(查看的话,直接可以对当前的元素进行操作);
并且对于在某个位置插入,删除时,边界的把握很重要。 删除时:index 不能小于0 ,index不能大于(size -1) 即(index < 0 || index > (size-1)){return -1}退出;因为0是第一个元素下标,(size-1)是最后一个元素的下标。但是在插入的时候,if(index < 0 || index >size) {return -1} ,size位置是链表有效元素后的第一个无效位置,在那个位置可以插入。这个很重要!!! 还有index的位置怎么计算??(dummyHead虚拟头节点它的下标是(-1),head头结点的下标是(0),然后下一个结点的下标(1)......(2)......)我们的代码的实现也是根据这个顺序;还有要注意的,每添加一个元素,或者删除一个元素,一定要size++或者size--;
代码实现:
题目:翻转链表
题意:反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
解题思想:
我们使用三指针的方法。pre指向nullptr, cur指向 head ,tmp ; 然后先让tmp指向cur->next;再让cur 指向pre,完成当前这个结点的逆转。然后更新pre 和cur 都指向下一个新的结点,继续循环。直到cur为空退出循环。
细节注意:
循环条件是判断cur; 然后cur pre tmp 的更新顺序。一定要弄清楚!!!!
首先一定是先更新 pre 再是 cur 。再完成一个结点的逆转之后。我们先更新pre = cur;再更新cur = tmp;这样才能都往下走一步。如果先更新cur 的话,那么pre就不知道指向哪里,不可以。返回的时候,返回的是pre指针。pre指针是新链表头结点。一定要深刻理解!!
代码实现: