链表反转以前我已经写过相关的文章了,可是如今去看下以前写过的文章,感受太过于简短,只是贴出了代码,并无把核心的东西讲出来。趁着周末,仍是把这道简单的题从新梳理一下。javascript
众所周知,JavaScript的数组提供了不少有用的操做数组的方法,其中Array.prototype.reverse
方法就能够将数组里面的数字反转。用reverse
这个函数反转数组很简单,这里看下代码如何操做:前端
let array = [1, 2, 3, 4, 5]
array.reverse() // [5, 4, 3, 2, 1]
复制代码
这样的代码很简单,可是咱们依旧不知道是怎么反转的。下面来看下一种常见的思路————头尾交换,以下图:
数组长度为3:java
数组长度为4:算法
因此长度为 n的数组须要交换 n / 2 + 1 次,由此咱们能够得出下面的代码:数组
let array = [1, 2, 3, 4, 5]
for(let i = 0; i < array.length / 2; i ++){
[array[i], array[array.length - i - 1]] = [array[array.length - i - 1], array[i]]
}
console.log(array) // [5, 4, 3, 2, 1]
复制代码
什么是链表?个人理解是一个长度为n,没法经过下标来遍历,只能经过当前节点来访问下一个节点的链式结构。 那么废话很少说,先来构造一个简单的链表:微信
//节点构造函数
function Node(val){
this.val = val
this.next = null
}
//定义链表
function List(array){
this.head = null
let i = 0,temp = null
while(i < array.length){
if( i === 0){
this.head = new Node(array[i])
temp = this.head
}else{
let newNode = new Node(array[i])
temp.next = newNode
temp = temp.next
}
i++
}
}
//遍历链表
function traverseList(listHead){
while(listHead){
console.log(listHead.val)
listHead = listHead.next
}
}
复制代码
以上是一个链表的简单实现,不懂的朋友能够翻看一下数据结构与算法 接下来划重点:链表只能由当前节点访问下一个节点,没法经过下标来访问链表元素
一开始没有想到办法,后来我用了一种比较奇葩的方法————将链表的值存进数组,反转数组之后再从新赋值,代码以下:数据结构
/** * @param {ListNode} head * @return {ListNode} */
var reverseList = function (head) {
let temp = head,
result = []
while (temp != null) {
result.push(temp.val)
temp = temp.next
}
temp = head, i = 0
result.reverse()
while (temp != null) {
temp.val = result[i++]
temp = temp.next
}
return head
};
复制代码
可是这显然没有利用到链表的特性————即由当前结点访问下一个节点。后来我在LeetCode的讨论看到这种思路————局部反转构成总体反转 啥意思呢?好比说:函数
var reverseList = function (head) {
let pre = null
while (head) {
next = head.next
head.next = pre
pre = head
head = next
}
return pre
};
复制代码
思路是否是很简单呢?这样简单的思路当时我却没有想到...反思ing......ui
从数组的反转到链表的反转,咱们能够得出一个结论:思惟不能僵化(逃,貌似很普通的一个算法————反转,能够有不少种作法。路过的朋友若是还知道其余算法,还请多多指教this
扫描下方的二维码或搜索「tony老师的前端补习班」关注个人微信公众号,那么就能够第一时间收到个人最新文章。