小题大做-判断回文链表

题干

编写一个函数,检查输入的链表是否是回文的。

难度为easy,但是感觉这个小题挺有意思,值的写写

深拷贝并反转链表

  1. 首先深拷贝链表(这里踩了一个坑,Object.assign({}, head)只能深拷贝head,但是head.next并没有被深拷贝,所以这个不可以;而JSON.parse(JSON.stringfy(head))可以完美深拷贝,但是当数据量过于庞大的时候,会执行栈溢出)
  2. 反转深拷贝以后的链表
  3. 比较两个链表
var isPalindrome1 = function(head) {
    let reverseHead = reverse(JSON.parse(JSON.stringify(head)))
    while (head) {
        if (head.val != reverseHead.val) {
            return false
        }
        head = head.next;
        reverseHead = reverseHead.next
    }
    return true
};

function reverse(head) {
    let prev = null;
    let cur = head;
    while (cur) {
        let next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next;
    }
    return prev
}

反思:这个方法是最先想到的方法,跳过深拷贝的坑不讲,回文链表其实只需要比较前一半就可以,而这个方法不知道链表的中点在哪里,只能比较全部链表,做了很多无用功。

将链表分别以正序和倒序存在两个不同的数组,比较两个数组

  1. 设置两个数组
  2. 循环链表,push与unshift方法向两个数组中依次存值
  3. 比较两个数组的前半部分
var isPalindrome1 = function(head) {
    let arr = [];
    let arr_ = [];
    while (head) {
        arr.push(head.val)
        arr_.unshift(head.val)
        head = head.next
    }
    for (let i = 0; i < parseInt(arr.length / 2); i++) {
        if (arr[i] != arr_[i]) {
            return false
        }
    }
    return true
};

反思:这个方法的确可以少做那一半的无用功,但是向数组存值是一个更耗时间的操作,还不如上一个呢

出入栈法

  1. 算出链表长度并算出中点位置
  2. 遍历链表,遍历中点前的元素时,向栈中存数据,遍历链表中点后的数据时,从栈中取数据。
  3. 后半部分当前遍历值与取出的值不相符的话,就不为回文,一样的话就是回文
var isPalindrome = function(head) {
    let len = getLen(head);
    let mid = Math.floor(len / 2);
    let arr = [];
    let index = 0;
    if (len % 2 == 0) {
        while (head) {
            if (index < mid) {
                arr.push(head.val);
            } else {
                let tmp = arr.pop();
                if (tmp != head.val) {
                    return false
                }
            }
            index++;
            head = head.next
        }
        return true
    } else {
        while (head) {
            if (index < mid) {
                arr.push(head.val);
            } else if (index == mid) {

            } else {
                let tmp = arr.pop();
                if (tmp != head.val) {
                    return false
                }
            }
            index++;
            head = head.next
        }
        return true
    }
};

function getLen(head) {
    let result = 0;
    while (head) {
        result++;
        head = head.next;
    }
    return result
}

反思:这个方法写起来很麻烦,因为要判断链表长度为单数还是双数,并且依然需要向数组存取值,性能消耗也不小

反转链表后半部分

  1. 快慢指针法,找到链表中点并返回
  2. 将中点.next反转
  3. 比较原数组与反转后的链表
var isPalindrome = function(head) {
    if (!head) return true;
    let midReverse = reverse(getMid(head).next);
    while (midReverse) {
        if (midReverse.val != head.val) {
            return false
        }
        midReverse = midReverse.next;
        head = head.next;
    }
    return true
}

function getMid(head) {
    let fast = slow = head;
    while (fast.next && fast.next.next) {
        fast = fast.next.next;
        slow = slow.next;
    }
    return slow
}

function reverse(head) {
    let prev = null;
    let cur = head;
    while (cur) {
        let next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next;
    }
    return prev
}

反思:此方法不需要向数组存值,也不需要做一半的无用功。nice

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值