【典例】 链表经典列题@链表

本文介绍了链表排序、删除排序链表中的重复元素、重排链表和从链表中删除总和值为零的连续节点等经典问题的解题思路。通过双指针、排序和特殊条件判断等方法,帮助读者理解链表操作并提升解决链表问题的能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信大家再初学数据结构时也会和我遇到相同的情形遇到题目无法构成有效的思路。

通过不断地练习题目我相信我们也会变成大佬的 ,也会拿到大厂offer。😀


链表排序

首先我们根据题目了解到这题解题思路 大概会用到 ① 双指针链表排序 

1.设置fast和slow两个指针利用fast走两步slow走一步的原理将slow置为链表的中间节点,而此时pre指针指向slow指针前一个结点。所以现在将pre指针置为null,就可以将原有链表分为两部分。

2.将两部分链表进行排序。以便完成下一步动作。

3.到这一步 两部分链表皆以排好序,创建新的节点头 比较两个链表头节点的值,使用新链表结点与值小的一方连接。

4.完成全部步骤 只需返回设置的结点即可。

class Solution {
    public ListNode sortList(ListNode head) {
       return mergeSort(head); }
    ListNode mergeSort(ListNode head){
        if(head == null || head.next == null) return head;
        ListNode fast = head;
        ListNode slow = head;
        ListNode pre = null;
        while(fast != null && fast.next != null){//使用快慢指针找出链表中间位置结点
            pre = slow;//此时pre 在last前一个位置上
            fast = fast.next.next;
                slow = slow.next;
          }
           pre.next = null;//使得pre的next为空 这样链表就分为两部分 一部分以head开头 一部分以slow开头
         ListNode l1 =  mergeSort(head);使用归并排序进行对链表两部分进行排序
         ListNode l2 =  mergeSort(slow);
         return  merge(l1, l2);
        }
      ListNode merge(ListNode l1, ListNode l2){
        ListNode newhead = new ListNode(0);创建新的链表头
        ListNode cur3 = newhead;
      while(l1 != null && l2 != null){
         if(l1.val < l2.val){比较两个链表的值谁小
             cur3.next = l1;用cur3 接上
             l1 = l1.next;
             }else{
             cur3.next = l2;
             l2 = l2.next;
            }
            cur3 = cur3.next;
          }
          if(l1 != null){
              cur3.next = l1;
          }
          if(l2 != null){
              cur3.next = l2;
          }
          return newhead.next;
    }
}

删除排序链表中的重复元素 

  

解题思路

和往常解题思路一样先判断特殊情况

创建新的节点连接头节点 此时利用l2来判决  看 l2.val值和 l2.next.val是否相同。

这一步给大家介绍

当我们进入if循环里时 就代表 l2.val == l2.next.val 当我们while走完   就代表当前值和下一个值不同

此时呢我们还在 if 里面 为了防止紧跟这的还是一组相同的值 我们需要在循环里持续这一句持续判断。

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null) return head;
      ListNode newhere = new ListNode (0);创建新的节点
      newhere.next = head;
      ListNode l1 = newhere;
      ListNode l2 = head;
   while(l2 != null){循环条件 l2不能为空
      if(l2.next != null && l2.val == l2.next.val){此时判断l2 的val 和l2.next的val是否相同
            while(l2.next != null && l2.val == l2.next.val){这一步是至关重要的 会在解题思路中讲清
                l2 = l2.next;
            }
            l1.next = l2.next;
            l2 = l1.next;
          }else{
              l1 = l2;
              l2 = l2.next;
          }
      }
      
       return newhere.next;
     
    }
}

 重排链表

 

  

了解题意 是要将第一个和最后一个连接 第二个和倒数第二个相连 依次往后 直到最中间元素位置为止

使用快慢指针进行操作 找到中间元素 分为两个链表部分 将后半部分进行逆置 使最后一个元素变为第一个元素然后进行合并。

class Solution {
    public void reorderList(ListNode head) {
    ListNode fast = head.next;
    ListNode slow = head;
    while(fast != null && fast.next != null){快慢指针进行操作
        fast = fast.next.next;
        slow = slow.next;
    }
    ListNode pre = slow.next;
    ListNode cur1 = null;
    slow.next = null;
    while(pre != null){反转链表操作
    ListNode cur =  pre.next;
    pre.next = cur1;
    cur1 = pre;
    pre = cur;
 }
 ListNode cur3 = head;
  ListNode l3 = cur1;
   while(cur3 != null && l3 != null){
       ListNode l1 = cur3.next;将两个链表合并
       ListNode l2 = l3.next;
        cur3.next = l3;
        cur3 = l1;
          l3.next = cur3;
        l3 = l2;


   }
    }
}

 从链表中删除总和值为零的连续节点

 

解题思路

持续遍历结点并将其和加在一起 进行判断为零时进行操作。

class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
       ListNode pre = new ListNode(0);
       ListNode cur =pre;
       pre.next = head;
      while(pre != null){
           ListNode cur1 = pre.next;
           int sum = 0;
           while(cur1 != null){计算和值为零时
               sum += cur1.val;
               cur1 = cur1.next;
               if(sum == 0){当寻找到所需时
                   pre.next = cur1;进行删除
                   break;
               }
           }
           if(cur1 == null) pre = pre.next;
      
      }
       return cur.next;
    }
}

 反转链表

当我们看到这题时会想到我们应该先找到right 后面一个结点和 left 前一个结点。这样方便我们进行逆置。事实也是如此 

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
     ListNode node = new ListNode(0);
     node.next = head;
     ListNode pre = node;
     for(int i = 1; i < left; i ++){先找到left前一个结点
         pre = pre.next;

     }
     ListNode haed = pre.next;将haed插入要逆置的第一元素
     for(int j = left; j < right; j ++  ){下面这部分进行逆置
         ListNode nex = haed.next;
         haed.next = nex.next;
         nex.next = pre.next;
         pre.next = nex;
     }
     return node.next;
    }最后输出头结点
}

相信明天更好!!!🤭

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值