给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路:这题有点投机取巧了,通过观察可以发现,两两交换是由规律的,下面用第几个元素来代表交换后的链表。 2 1 4 3 6 5 8 7 10 9…可以看到遇到第n个节点,如果n是奇数,下一个元素就是n+3,如果n是偶数,下个元素就是n-1。由于待会遍历的数组,所以索引下标和n是差1的,所以以上的结论要反过来。如果链表长度是偶数,那就会全部遍历完,如果是奇数,那还会剩余最后一个,我们需要在循环结束后手动添加进链表。
/*
Leetcode24
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
* */
public class Leetcode24 {
public ListNode swapPairs(ListNode head) {
// 如果head节点为空 或者 只有一个节点 直接返回head即可
if(head == null || head.next == null){
return head;
}
// 用arraylist来存储Listnode
List<ListNode> list = new ArrayList<>();
while(head!=null){
list.add(head);
head = head.next;
}
// 创建一个带头节点的空链表
ListNode result = new ListNode(0,null);
ListNode temp = result;
// 由于是两两反转,所以第一个是从下标为1的地方开始索引
int index = 1;
// 索引小于 长度 -1 时 执行循环
while(index <= list.size()-1){
temp.next = list.get(index);
temp = temp.next;
// 如果索引是偶数,说明返回的是第奇数个节点,那么下一个返回的节点是下一组的后面一个
if(index % 2 == 0){
index = index + 3;
}else {
// 如果是奇数 说明访问的是 第 偶数个节点,那么下一个返回的节点是他的前驱
index--;
}
}
// 如果链表的个数为奇数个,那我们添加的时候就会漏掉最后一个
// 这里把它加上即可
if(list.size() % 2 == 1){
temp.next = list.get(list.size()-1);
temp = temp.next;
}
// 让最后一个节点的后继指向null
temp.next = null;
return result.next;
}
}
这样相当于遍历了两次链表,只不过第二次遍历是随机遍历数组,效率更高一点。时间复杂度是O(2n) 也就是 O(n)