算法实现----链表(六)

博客介绍了几种链表相关的算法操作,包括怪异的节点删除方式、向有序环形单链表插入新节点、合并两个有序链表以及按左右半区重新组合单链表,这些操作均围绕链表数据结构展开。

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

一种怪异的节点删除方式

package linked;

public class RemoveNodeOnlyByValue {
	
	/**题目:一种怪异的节点删除方式
	 * 
	 **要求:链表节点值为int类型,给定一个链表中的节点node,但不给定整个链表的头节点
	 * 		 如何在链表中删除node?请实现这个函数,并分析其中会出现的问题。
	 * 		时间复杂度达到O(1).
	 **/
	public static void main(String[] args) {
		
	}
	
	/*
	 * 	本体思路很简单,只需举例即可说明具体的做法,但存在很大问题
	 * 	 例如:1>2>3>null,只给要删除的节点2,而不知道头节点。
	 * 	那么只需要将节点2中的值改成节点3中的值,然后删除节点3即可。
	 * 
	 * 	该解法存在两个问题:
	 * 	1.无法删除最后一个节点(将该节点直接置为null也不行,
	 * 	这样只是将该引用指向null,但该节点的next指针还是指向最后一个节点的内存地址。
	 * 	要想让前一个节点的指针指向null,必须找到前一个节点,但是无法实现)
	 * 
	 * 	2.即使不是删除最后一个节点,
	 * 这样的做法实质上只是简单地将节点的值改成下一个节点的值,
	 * 然后删除了下一个节点。
	 */
	public static void removeNodeWired(Node node) {
		
	}
	
	public static void removeNode(Node node) {
		if(node == null) {
			return;
		}
		if(node.next == null) {
			throw new RuntimeException("can't remove the last node");
		}
		node.value = node.next.value;
		node.next = node.next.next;
	}
}	

向有序的环形单链表中插入新节点

public class InsertNum {
	/**题目:向有序的环形单链表中插入新节点
	 * 
	 **要求:一个环形链表从头节点head开始不递减,同时由最后的节点指向头节点。
	 *		给定这样一个环形单链表的头节点head和一个整数num,请生成节点值为num
	 *		的新节点,并插入到这个环形链表中,保证调整后的链表依然有序。
	 * 		时间复杂度达到O(n),空间复杂度达到O(1).
	 **/
	public static void main(String[] args) {
		Node node1 = new Node(1);
		Node node2 = new Node(3);
		Node node3 = new Node(4);
		Node node4 = new Node(6);
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		node4.next = node1;
		Node newNode = insertNum(node1, 2);
		Node cur = newNode;
		for(int i = 1;i <= 5;i++) {
			System.out.println(cur.value);
			cur = cur.next;
		}
	}
	
	public static Node insertNum(Node head,int num) {
		Node newNode = new Node(num);
		if(head == null) {
			newNode.next = newNode;
			return newNode;
		}
		Node cur = head.next;
		Node pre = head;
		Node next = null;
		while(cur != head) {
			if(pre.value <= num && num <= cur.value) {
//				pre.next = newNode;
//				newNode.next = cur;
//				return head;
				break;
			}
			pre = cur;
			cur = cur.next;
		}
		pre.next = newNode;
		newNode.next = cur;
		return num >= pre.value?head:newNode;
	}

}

合并两个有序的链表

public class MergeTwoLinked {
	
	/**题目:合并两个有序的链表
	 * 
	 **要求:给定两个有序单链表的头节点head1和head2,长度分别为N和M
	 *		请合并两个有序的链表,合并后的链表依旧有序,并返回新链表的头节点。
	 *		时间复杂度为O(M+N),空间复杂度为O(1)
	 *
	 **例如:0>2>3>7>null和1>3>5>7>9>null
	 *		合并后的链表为:0>1>2>3>3>5>7>7>9>null
	 **/
	public static void main(String[] args) {
		Node node1 = new Node(0);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(7);
		Node node5 = new Node(1);
		Node node6 = new Node(3);
		Node node7 = new Node(5);
		Node node8 = new Node(7);
		Node node9 = new Node(9);
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		node4.next = null;
		node5.next = node6;
		node6.next = node7;
		node7.next = node8;
		node8.next = node9;
		node9.next = null;
		Node newNode = merge(node1, node5);
		while(newNode != null) {
			System.out.println(newNode.value);
			newNode = newNode.next;
		}
	}
	
	public static Node merge(Node head1,Node head2) {
		if(head1 == null || head2 == null) {
			return head1 == null? head2:head1;
		}
		Node cur1 = head1;
		Node cur2 = head2;
		Node newNode = head1.value >= head2.value?head2:head1;
		if(newNode == head2) {
			cur2 = cur2.next;
		}else {
			cur1 = cur1.next;
		}
		while(cur1 != null && cur2 != null) {
			if(cur1.value >= cur2.value) {
				newNode.next = cur2;
				cur2 = cur2.next;
			}else {
				newNode.next = cur1;
				cur1 = cur1.next;
			}
			newNode = newNode.next;
		}
		newNode.next = cur1==null?cur2:cur1;
		
		return head1.value >= head2.value?head2:head1;
	}
}

按照左右半区的方式重新组合单链表

public class LeftRightMerge {
	/**题目:按照左右半区的方式重新组合单链表
	 *
	 **要求:给定一个单链表的头节点head,链表长度为N;
	 *		如果N为偶数,那么前N/2个节点为左半区,后N/2个节点为右半区;
	 *		如果N为奇数,那么前N/2个节点为左半区,后N/2+1个节点为右半区;
	 *		左半区从左至右依次记为L1>L2>...,右半区从左至右依次记为R1>R2>...
	 *		请实现一个函数将单链表调整为L1>R1>L2>R2>...
	 *		时间复杂度请达到O(N),空间复杂度请达到O(1)
	 *
	 **例如:1>null,调整后为1>null;
	 *		1>2>null,调整后为1>2>null;
	 *		1>2>3>null,调整后为1>2>3>null;
	 *		1>2>3>4>null,调整后为1>3>2>4>null;
	 *		1>2>3>4>5>null,调整后为1>3>2>4>5>null;
	 *		1>2>3>4>5>6>null,调整后为1>4>2>5>3>6>null;
	 **/
	public static void main(String[] args) {
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);
		Node node5 = new Node(5);
		Node node6 = new Node(6);
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		node4.next = node5;
		node5.next = node6;
		node6.next = null;
		
		Node newNode = merge(node1);
		while(newNode != null) {
			System.out.println(newNode.value);
			newNode = newNode.next;
		}
	}
	
	public static Node merge(Node head) {
		if(head == null || head.next == null || head.next.next == null) {
			return head;
		}
		Node cur1 = head;
		Node cur2 = head;
		while(cur1.next != null && cur1.next.next != null) {
			cur2 = cur2.next;
			cur1 = cur1.next.next;
		}
		cur2 = cur1.next == null?cur2:cur2.next;
		Node mid = cur2;
		cur1 = head;
		Node cur1Next = null;
		Node cur2Next = null;
		while(cur1.next != mid) {
			cur1Next = cur1.next;
			cur2Next = cur2.next;
			cur1.next = cur2;
			cur2.next = cur1Next;
			cur1 = cur1Next;
			cur2 = cur2Next;
		}
		cur1.next = cur2;
		return head;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值