Java 链表合并相同元素
链表是一种常见的数据结构,它由多个节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。在实际开发中,我们经常需要对链表进行各种操作,如插入、删除、查找等。其中一个常见的操作是合并相同元素,即将链表中重复的元素合并为一个。
问题描述
给定一个链表,需要编写一个函数来合并链表中相同的元素。具体而言,如果链表中某两个相邻的元素值相同,则将它们合并为一个元素,并从链表中删除一个元素。最终,合并操作后的链表中不会存在相邻的相同元素。
示例
考虑以下链表作为输入:
1 -> 1 -> 2 -> 3 -> 3
经过合并相同元素操作后,链表应该变为:
1 -> 2 -> 3
解决方案
要解决这个问题,我们可以使用迭代的方式遍历链表,并比较每个节点与其后继节点的值是否相同。如果相同,则将当前节点的指针指向后继节点的后继节点,从而实现删除一个节点的效果。代码示例如下:
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
class Solution {
public ListNode merge(ListNode head) {
ListNode curr = head;
while (curr != null && curr.next != null) {
if (curr.val == curr.next.val) {
curr.next = curr.next.next;
} else {
curr = curr.next;
}
}
return head;
}
}
在上面的代码中,我们定义了一个 ListNode
类来表示链表的节点,并且每个节点包含一个整数值和一个指向下一个节点的指针。Solution
类中的 merge
方法接受一个链表的头节点作为参数,并返回合并相同元素后的链表的头节点。
性能分析
这个算法的时间复杂度是 O(n),其中 n 是链表的长度,因为我们只需一次遍历整个链表。空间复杂度是 O(1),因为我们只使用了常数级别的额外空间。
测试
为了验证我们的算法是否能正确地合并链表中的相同元素,我们可以编写一些测试用例,并使用 JUnit 框架执行测试。以下是一个示例测试用例:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class SolutionTest {
@Test
void testMerge() {
ListNode head = new ListNode(1);
head.next = new ListNode(1);
head.next.next = new ListNode(2);
head.next.next.next = new ListNode(3);
head.next.next.next.next = new ListNode(3);
Solution solution = new Solution();
ListNode merged = solution.merge(head);
Assertions.assertEquals(1, merged.val);
Assertions.assertEquals(2, merged.next.val);
Assertions.assertEquals(3, merged.next.next.val);
Assertions.assertNull(merged.next.next.next);
}
}
执行上述测试用例后,如果没有抛出任何异常,则说明我们的算法通过了测试。
总结
本文介绍了如何使用 Java 合并链表中的相同元素。我们通过遍历链表并比较每个节点与其后继节点的值,实现了删除链表中相同元素的操作。我们还对算法的时间复杂度和空间复杂度进行了分析,并提供了一个示例测试用例来验证算法的正确性。最后,我们可以将这个算法应用到实际的开发中,以解决类似的问题。