【算法入门】递归与迭代

175 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

前言

作为一个算法萌新,很长一段时间总是对递归迭代的概念含糊不清,只知道用起来都是通过循环执行代码去解决一些问题,但是对于自己用的究竟算递归还是迭代傻傻分不清楚,今天就跟大家一起来好好捋一捋

迭代与递归

概念

  • 迭代

迭代时重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果

2022-12-10 13 23 48

  • 递归

指在函数的定义中使用函数自身的方法

  • 根据返回值判断
  • 根据操作节点的前后位置(二叉树相关——前序,中序,后序)

2022-12-10 13 24 31

这么一看两者的区分还是很明显,通过有没有调用自身,即可判断是递归还是迭代

不过有时突然想起还是容易记混,个人从字面理解的角度出发总结一下:迭代就是一代一代执行下去,很容易与for循环关联起来;递归,归就是回到原来的地方(方法),即再次调用自身

做题

回文链表

234. 回文链表 - 力扣(LeetCode)

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

回文指结构数值具有对称性

我们常见判断一个字符串是否是回文字符串,可以使用两个指针,一个最左边一个最右边,两个指针同时往中间靠,判断所指的字符是否相等

  • 迭代解法

首先用迭代的思路我们就需要去遍历链表,并且由于无法取得链表的长度,我们无法使用 for 去遍历,只能用while 通过判断链表节点是否为空完成遍历,取得数值数组后,使用双指针判断数组是否对称来推断是不是回文链表

var isPalindrome = function(head) {
    // 使用迭代获取链表对应的数组
    const list = []
    let root = head
    while (root) {
        list.push(root.val)
        root = root.next
    }
    // 使用双指针判断数组是否对称
    let left = 0
    let right = list.length - 1
    while(left < right) {
        if (list[left] != list[right]) {
            return false
        } else {
            left ++
            right --
        }
    }
    
    return true
};
  • 递归解法

说实话这道题用递归着实不好想,首先要能想到,虽然无法获取链表的长度,但是从后打印链表的数值我们是可以做到的

先看下面的一段代码(从最后开始往前打印)

function reverseLog(head) {
    if (!head) {
        return
    }
    reverseLog(head.next)
    console.log(head.val)
}

如果理解了上面的逻辑,那么这道题的递归做法就容易多了

var isPalindrome = function(head) {
    var tmp = head
    function check(head) {
        if (!head) {
            return true
        }
        const res = check(head.next) && (tmp.val == head.val)
        tmp = tmp.next
        return res
    }
    return check(head)
};