代码随想录笔记【链表】(二)

一、移除链表元素

       让被移除的元素的前一个元素直接指向被移除元素的下一个元素,即可完成元素的移除,同时需要考虑到被移除的是第一个元素,那么它就不存在之前的元素。

1.不使用虚拟头节点

首先考虑头节点为目标元素

while(head != NULL && head -> val == target){

        head = head -> next;  //记得释放内存

}

cur = head;

while(cur != null && cur -> next != Null){

        if(cur ->next-> target == target)//当下一个元素为目标数时,直接由当前节点指向下下个节点

                cur -> next = cur -> next -> next;

        else cur = cur -> next;

}

return head;

2.使用虚拟头节点

当使用虚拟头节点时,所有节点(包括头节点)都有前一个节点和下一个节点,这样对所有节点的操作变得一致,不需要额外判断头节点

dummy head = new ListNode();

dummy head -> next = head;

cur = dummy head;

while( cur -> next != NULL){

        if(cur -> next -> val == target){

                cur -> next = cur -> next -> next;

        }

        else cur = cur-> next;

}

return dummy head -> next;

二、设计链表

统一使用虚拟头节点(使用虚拟头节点方便设置新的头节点)

1.获取第n个节点的数值

LinkedNode* dummy head = new LinkedNode();

dummy head -> next = head;

cur = dummy head -> next;

while( n ){

        cur = cur -> next

        n--;

}

return cur -> val;

2.头部插入节点

LinkedNode* dummy head = new LinkedNode();

dummy head -> next = head;

cur = dummy head -> next;//先保存好原来的头节点

LinkedNode* newnode = new LinkedNode(val);

newnode -> next = dummy head -> next;

dummy head -> next = newnode;

size++;

3.尾部插入节点

Newnode = new LinkedNode(val)

cur = dummy head;

while(cur -> next !=NULL){

        cur = cur -> next;

}

cur ->  newnode;

4.在第n个节点前插入节点

newnode = new node(val);

cur = dummy head;

while(n--){

        cur = cur -> next;

}

newnode -> next = cur -> next;//先将第n个节点储存好,在设计第n-1个节点

cur -> next = newnode;

size++;

5.删第n个节点

cur = dummy head;

while(n--){

      cur = cur -> next;

}

cur -> next = cur -> next -> next;

size--;

三、翻转链表

1.双指针法

cur = head;

pre = NULL;//pre负责新指针

while( cur ){

      temp = cur -> next;

      cur -> next = pur;

      pre = cur;

      cur = cur-> temp;

}

return pre;

2.递归写法(原理同上)

reverse(cur,pre){

      if(cur == NULL) return pre;

      temp = cur -> next;

      cur -> next = pre;

      return reverse(temp,cur);//不断重复reverse这一动作直到反转完成

}

reverselist(head){

      return reverse(head,NULL);

}

四、两两交换链表节点

1.虚拟头节点

dummyhead -> next = head;

cur = dummyhead;

while(cur -> next !=NULL && cur -> next -> next != NULL){ //顺序很重要,因为如果cur ->next为空的话,不存在cur ->next ->next,就会报错

      temp = cur -> next//每一次反转记得保存下下下一个节点(未参与反转的节点)和参与反转的节点

      temp1 = cur -> next -> next -> next;

      cur -> next = cur -> next -> next;

      cur -> next -> next = temp;

      temp -> next = temp1

      cur = cur -> next -> next;

}

return dummyhead -> next;

五、删除链表中倒数第n个节点

利用双指针,先让快指针走n+1步,然后快慢同时走,这样当快指针指到NULL时,慢指针刚好指到倒数第n个之前的呢个节点,便可以进行删除操作。

fast  =  dummyhead;

slow = dummyhead;

n++;

while(n-- && fast != NULL){

      fast = fast -> next;

}

while(fast != NULL){

      fast = fast -> next;

      slow = slow -> next;

}

temp = slow -> next;

slow -> next =slow -> next -> next;

delete temp;

return dummyhead -> next

六、链表相交

先让长的链表减去短的链表,可以得出两条链表长度的差,先让长的链表往后推进这个差值,然后长短一起向前推进,并判断指针是否相等

curA = headA;

curB = headB;

int lenA = 0, lenB = 0;

while (curA != NULL) {    // 求链表A的长度

      lenA++;

      curA = curA->next;

}

while (curB != NULL) {    // 求链表B的长度

     lenB++;

     curB = curB->next;

}

curA = headA;

curB = headB;     // 让curA为最长链表的头,lenA为其长度

if (lenB > lenA) {

    swap (lenA, lenB);

    swap (curA, curB);

}        

int gap = lenA - lenB;   // 求长度差

while (gap--) {     // 让curA和curB在同一起点上(末尾位置对齐)

      curA = curA->next;

}

while (curA != NULL) {  // 遍历curA 和 curB,遇到相同则直接返回

if (curA == curB) {

      return curA;

}

curA = curA->next;

curB = curB->next;

}

return NULL;

七、环形链表

1.判断环形链表:定义两个指针,快指针和慢指针,看他们是否相遇。

快指针每次走两步,慢指针每次走一步,快指针就相对于慢指针每次走一步,若相遇,就一定有环。

2.寻找环形链表的入口:假设入口处距离起点为x,入口距离相遇处为y,相遇处距离入口为z

相遇时,慢指针走了x+y,快指针走了x+y+n(y+z)

因为快指针一次走两步,慢指针一次走一步

可以得到2(x+y) = x+y+n(y+z)

x+y = n(y+z)   n => 1

x = (n-1)(y+z)+z

可见当一个点从相遇点出发,另一个点从起点出发,一定能在环形入口处相遇。

fast = head;

slow = head;

while(fast != NULL && fast -> next != NULL){

fast = fast ->next->next;

slow = slow->next;

if(fast == slow){

index1 = fast;

index2 = head;

while(index1 != index2){

    Index1 = index1->next;

    Index2 = index2->next;

}

return index1;

}

return NULL;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值