JavaScript从反转数组到链表反转

链表反转之前我已经写过相关的文章了,但是现在去看下之前写过的文章,感觉太过于简短,只是贴出了代码,并没有把核心的东西讲出来。趁着周末,还是把这道简单的题重新梳理一下。

如何反转一个数组?

众所周知,JavaScript的数组提供了很多有用的操作数组的方法,其中Array.prototype.reverse方法就可以将数组里面的数字反转。用reverse这个函数反转数组很简单,这里看下代码如何操作:

let array = [1, 2, 3, 4, 5]
array.reverse()     // [5, 4, 3, 2, 1]
复制代码

这样的代码很简单,但是我们依旧不知道是怎么反转的。下面来看下一种常见的思路————头尾交换,如下图:
数组长度为3:

  • 1
  • 2
  • 3
  • 3
  • 2
  • 1

数组长度为4:

  • 1
  • 2
  • 3
  • 4
  • 4
  • 2
  • 3
  • 1
  • 4
  • 3
  • 2
  • 1
数组长度为5:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 5
  • 2
  • 3
  • 4
  • 1
  • 5
  • 4
  • 3
  • 2
  • 1

所以长度为 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的讨论看到这种思路————局部反转构成整体反转 啥意思呢?比如说:

  • 1
  • 2
  • 3
  • 4
  • 2
  • 1
  • 3
  • 4
  • 3
  • 2
  • 1
  • 4
  • 4
  • 3
  • 2
  • 1
根据上面过程的启发,我们很容易可以得到如下的代码:
var reverseList = function (head) {
    let pre = null
    while (head) {
        next = head.next
        head.next = pre
        pre = head
        head = next
    }
    return pre
};
复制代码

思路是不是很简单呢?这样简单的思路当时我却没有想到...反思ing......

总结

从数组的反转到链表的反转,我们可以得出一个结论:思维不能僵化(逃,貌似很普通的一个算法————反转,可以有很多种做法。路过的朋友如果还知道其他算法,还请多多指教

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值