206 链表反转 99.25%

function ListNode(val) {
	this.val = val;
	this.next = null;
}

var reverseList = function(head) {
	let pre = null, n = null
	while(head){
		n = head.next
		head.next = pre
		pre = head
		head = n
	}
	return pre
};

let l1 = new ListNode(1)
let l2 = new ListNode(2)
let l3 = new ListNode(3)
let l4 = new ListNode(4)
let l5 = new ListNode(5)
l1.next = l2
l2.next = l3
l3.next = l4
l4.next = l5

let n = reverseList(l1)
while(n){
	console.log(n.val)
	n = n.next
}

24 两两交换链表中的节点 88.76%

function ListNode(val) {
	this.val = val;
	this.next = null;
}

var swapPairs = function(head) {
	let pre = null, ret = null
	if (head && !head.next) return head

	while (head && head.next){
		let behind = head.next
		if (!ret) {ret = behind;}
		head.next = head.next.next
		behind.next = head
		if (pre){
			pre.next = behind
		}
		pre = head
		head = head.next
	}
	return ret
};

let l1 = new ListNode(1)
let l2 = new ListNode(2)
let l3 = new ListNode(3)
let l4 = new ListNode(4)
let l5 = new ListNode(5)
l1.next = l2
l2.next = l3
l3.next = l4
l4.next = l5

let n = swapPairs(l1)
while(n){
	console.log(n.val)
	n = n.next
}

141 环形链表 89.44%

// first 89.44%
var hasCycle = function(head) {
	let s = new Map();
	let idx = 0
	while(head){
		if (!s.has(head)){
			s.set(head, idx++)
		}else{
			return s.get(head)
		}
		head = head.next
	}
	return -1
};

上面这个用map能够返回尾部是接在哪个节点上了。但是题目实际上不需要,下面的解法2才是题目需要的,这个就更快了。两者内存基本没有差别。但是速度快了很多。

// 99.19%
var hasCycle = function(head) {
	let s = new Set();
	while(head){
		if (!s.has(head)){
			s.add(head)
		}else{
			return true
		}
		head = head.next
	}
	return false
};

上面两个的复杂度都是O(n),因为要遍历一遍链表。还有一个正常人想不到的办法,叫龟兔赛跑(快慢指针),用两个指针,一个一次走一步,一个一次走两步,那么如果有环,这两个就一定会相遇。

var hasCycle = function(head) {
	let slow = fast = head;
	while(slow && fast && fast.next){
		slow = slow.next
		fast = fast.next.next
		if (slow === fast) return true
	}
	return false
};

实际结果是这个显然不如前面那个好,速度82.27%,比之前慢,但是因为少用了一个set,所以空间上省了1M。