单链表定义
/**
* 单链表的定义
*/
public class ListNode {
// 存表的元素
public int value;
// 指针
public ListNode next;
public ListNode(int value) {
this.value = value;
}
}
public class ListNodeTest {
/**
* 单链表反转链表
* 时间复杂度o(n), 空间复杂度o(1)
*/
public static ListNode reverseList(ListNode head) {
// 当前结点的上一个结点
ListNode pre = null;
// 当前结点的下一个结点
ListNode next = null;
// 遍历
while (head != null) {
// 记录下一个结点的位置
next = head.next;
// 当前结点的尾指针(下一个结点)由原来的位置指向它前面的位置,也就是反转
head.next = pre;
// 前一个结点pre和当前结点的指针,都向后移一位
pre = head;
head = next;
}
// 返回反转之后的第一个结点(因为正常顺序的尾结点是null,所有反转时当前结点的值就是null)
return pre;
}
/**
* 单链表取中间结点
* 如果单链表个数是奇数,就取中间的结点
* 如果单链表个数是偶数,就取中间两个中前面的那个
* 思路: 规定了两个指针,一个快指针,一个慢指针,快指针每次走两步,慢指针每次走一步,
* 当快指针走完之后,慢指针的位置就是中间结点的位置
*/
public static ListNode getMid(ListNode head){
if (head == null) {
return head;
}
// 快指针,刚开始都是指向头部
ListNode fast = head;
// 慢指针,刚开始都是指向头部
ListNode slow = head;
// 因为快指针fast每次走两步,所有判断它的下一步和下两步为null时, 不能遍历
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 返回慢指针的位置
return slow;
}
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
node1.next = node2;
node2.next = node3;
node3.next = null;
System.out.println(getMid(node1).value);
ListNode node = reverseList(node1);
while (node != null) {
System.out.print(node.value + " ");
node = node.next;
}
}
}
/**
* 合并两个有序链表
*/
public class ListNodeTest2 {
/**
* 采用递归实现, 两个有序链表
* @param head1
* @param head2
* @return
*/
public static ListNode mergeTwoList(ListNode head1, ListNode head2) {
// 递归结束的条件
if (head1 == null && head2 == null) {
return null;
}
if (head1 == null) {
return head2;
}
if (head2 == null) {
return head1;
}
// 主要的逻辑
// 声明合并之后的头结点
ListNode head = null;
if (head1.value > head2.value) {
// 把head的头指针指向较小的那个
head = head2;
// head2.next:在剩余的结点中去找下一个结点
head.next = mergeTwoList(head1, head2.next);
} else {
head = head1;
head.next = mergeTwoList(head1.next, head2);
}
return head;
}
/**
* 采用非递归的方式
*/
public static ListNode mergeTwoList2(ListNode head1, ListNode head2) {
// 思路:分别遍历两个链表,把另一个链表合并到当前链表中,把首节点大的每一个元素合并到首节点小的那个链表
if (head1 == null || head2 == null) {
return head1 != null ? head1 : head2;
}
// 两个链表的头结点比较,先找到头结点比较小的那个,作为基准链表
ListNode head = head1.value < head2.value ? head1 : head2;
// cur1 指向的链表是基准的链表
ListNode cur1 = head == head1 ? head1 : head2;
// cur2 指向另一个链表
ListNode cur2 = head == head1 ? head2 : head1;
ListNode pre = null; // cur1前一个元素
ListNode next = null; // cur2 后一个元素
while (cur1 != null && cur2 != null) {
if (cur1.value <= cur2.value) {
pre = cur1;
cur1 = cur1.next;
} else {
next = cur2.next;
pre.next = cur2;
cur2.next = cur1;
pre = cur2;
cur2 = next;
}
}
pre.next = cur1 == null ? cur2 : cur1;
return head;
}
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
node1.next = node3;
node2.next = node4;
ListNode node = mergeTwoList2(node1, node2);
while (node != null) {
System.out.print(node.value + " ");
node = node.next;
}
}
}
参考资料:来源于网络