【算法】移除链表元素

69 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

题目

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

解题思路

关键词:链表;相同节点值

关键信息:递归求解;链式结构

删除相同节点值链表结构一般采用递归方法求解:遍历整个链表移除链表相应节点即可。

递归解法

public ListNode removeElements(ListNode head, int val) {
        // 递归
         if(head == null) return null;
          head.next = removeElements(head.next,val);
         if(head.val == val){
             return head.next;
         }else{
             return head;
        }   
}

插入头节点解法

如果不使用递归解法如果要遍历链表必然会找不到当前头节点了,在原链表头部插入一个节点可以帮助定位原链表头。

  1. 新建一个头节点执行链表头部。
  2. 循环遍历(起始点从head开始。
  3. 循环体中对节点值判断:等于对应值则移除该节点并指向下一个;不等于移位到下一个节点。
  4. 跳出循环后最后以新建节点为指针输出结果链表。
public ListNode removeElements(ListNode head, int val) {
	if(head == null) return null;
      ListNode newHead = new ListNode(0);
      newHead.next = head;
      ListNode temp = newHead;
      while(temp.next != null){ // 起始从head开始遍历
          if(temp.next.val == val){   // 判断是否等于指定值
             temp.next = temp.next.next; // 
          }else{
             temp = temp.next;
          }
      }
    
    return newHead.next;
}

PS:

1.为什么不直接移动newHead而新建一个temp?newHead作为指针指向下一个数就是节点头因此添加副本来移动。

2.为什么不使用head进行循环移动?移动head可能会导致newHead.next不在执行head了。

双循环解法

通过插入头节点解法思路可以再实现另外一种解法。

  1. 首先处理头节点为空或者值相等的情况。
  2. 处理完头节点特殊情况后增加head副本,通过副本循环移除符合条件的节点。
  3. 最终输出head即可。
public ListNode removeElements(ListNode head, int val) {
	while(head !=null && head.val == val){
             head = head.next;
         }
         if(head == null) return null;
          ListNode temp = head;
        while(temp.next != null){
                if(temp.next.val == val){  
                   temp.next = temp.next.next;
                }else{
                   temp = temp.next;
                }
        }
        return head;
}

参考