【题18 删除链表的节点】

【题18 删除链表的节点】
【题目一:在O(1)时间内删除链表节点】
给定单向链表的头指针和一个节点指针:定义一个函数在O(1)时间内删除该节点

分析:
常规做法是从链表的头节点开始,顺序遍历查找要删除的节点。
并在链表中删除该结点,想删除i,从a开始遍历。时间复杂度为O(n)
在这里插入图片描述

之所以需要从头开始查找,是因为我们需要得到将被删除的节点的前一个节点。在单向链表中,节点中没有指向前一个节点的指针,所以只好从链表的头节点开始顺序查找。
法二
如果把 下一个节点的内容复制到需要删除的节点上,覆盖原有的内容,再把下一个节点删除,就相当于把当前需要删除的节点删除了?
如图c要删除i,先把i的下一个节点j的内容复制到i然后把i的指针指向节点j的下一个节点,此时,删除j刚好把节点i删除了
在这里插入图片描述

问题:
如果要删除的节点位于链表尾部,没有下一个节点还要从头开始顺序遍历
注意:
如果链表中只有一个节点,又要删除链表的头节点(也是尾结点)
此时在删除节点之后,还需把链表的头节点设为null

分析时间复杂度:

  • 对于n-1个非尾节点,在O(1)时间把下一个节点的内存复制覆盖要删除的节点,并删除下一个节点。
  • 对于尾结点,需要顺序查找O(n)

总的平均时间复杂度是[(n-1)*O(1)+O(n)]/n 结果O(1)

上述代码并不完美,因为它基于一个假设,要删除的节点的确在链表中,需要O(n)时间才能 判断链表中是否包含某一结点

受到O(1)时间限制,不得不把确保节点在链表中的责任推给函数调用者。
实现

package ti18;

public class Lian {
	
	//删除链表中节点
	public static class ListNode{
		private int data;
		private ListNode next;
		public ListNode(int data,ListNode next){
			this.data = data;
			this.next = next;
		}
	}
	
	public static void deleteNode(ListNode head,ListNode node){
		//删除尾结点
		if(node.next == null){
			while(head.next != null){
				head = head.next;
			}
			head.next = null;
		}
		//删除节点是头节点
		else if(node == head){
			head = null;
		}
		//删除的是中间的普通节点
		else{
			node.data = node.next.data;
			node.next = node.next.next;
		}
	}
	
	public static void main(String[] args) {
		ListNode tail = new ListNode(1,null);
		ListNode c    = new ListNode(2,tail);
		ListNode b    = new ListNode(3,c);
		ListNode head = new ListNode(4,b);
		deleteNode(head,c);
		while(head != null){
			System.out.println(head.data);
			head = head.next;
		}
	}
}

【题目二:删除链表中重复的节点】
在一个排序的链表中,如何删除重复的节点?

(1) 确定删除函数的参数,输入待删除链表的头节点,头节点也可能被删掉
(2) 从头遍历整个链表,为了保证删除后的链表仍然相连,
(3) 要把当前节点的前一个节点和后面值比当前节点值大的节点相连,确保当前节点的前一个节点,始终与下一个没有重复的节点连接在一起。

实现

package ti18;

public class Lian2 {
	
	public static class ListNode{
		private int data;
		private ListNode next;
		public ListNode(int data,ListNode next){
			this.data = data;
			this.next = next;
		}
	}
	
	public static ListNode deleteDuplication(ListNode head){
		if(head == null || head.next == null){
			return head;
		}
		ListNode preNode = null;
		ListNode pNode = head;
		while(pNode != null){
			ListNode pNext = pNode.next;
			boolean needDelete = false;
			if(pNext !=null && pNode.data == pNext.data){
				needDelete = true;
			}
			if(!needDelete){
				preNode = pNode;
				pNode = pNode.next;
			}
			else{
				int value = pNode.data;
				ListNode toBeDelete = pNode;
				while(toBeDelete != null && toBeDelete.data == value){
					pNext = toBeDelete.next;
					toBeDelete = pNext;
				}
				if(preNode == null){
					head = pNext;
				}
				else
					preNode.next = pNext;
				pNode = pNext;
			}
		}
		return head;
	}
	
	public static void main(String[] args) {
		ListNode tail = new ListNode(5,null);
		ListNode c = new ListNode(4,tail);
		ListNode b = new ListNode(4,c);
		ListNode a = new ListNode(3,b);
		ListNode e = new ListNode(3,a);
		ListNode d = new ListNode(2,e);
		ListNode head = new ListNode(1,d);
		
		deleteDuplication(head);
		
		while(head != null){
			System.out.println(head.data+" ");
			head = head.next;
		}
	}
}

//方法二:递归实现
/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode deleteDuplication(ListNode pHead)
    {
        if(pHead == null ||pHead.next == null) return pHead;
        if(pHead.val == pHead.next.val){
            ListNode pNode = pHead.next;
            while(pNode != null && pNode.val == pHead.val){
                pNode = pNode.next;
            }
            return deleteDuplication(pNode);
        }else{
            pHead.next = deleteDuplication(pHead.next);
            return pHead;
        }
    }
}

参考:
1.《剑指offer》
2.https://blog.csdn.net/qfc8930858/article/details/83241509

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值