6月24日算法日记

142 阅读2分钟

1.反转链表

image-20220624213038938

解法

1.双指针

思路:

  1. 定义两个指针pre和cur,pre从链表头部之前的null开始,而cur则从链表的头部head开始依次向后移动
  2. 使用变量nextNode将当前结点的next保存下来,然后将当前结点的next指向上一个结点pre
  3. 循环向后(当前结点是否为null作为判断条件)移动pre和cur两个指针,pre = cur;cur=nextNode(这也是我为什么要使用变量nextNode保留当前结点的next的原因,如果不使用一个变量存储下来当前结点的next值,那么cur.next在上一步重新赋值时就会丢失)
  4. 最后返回pre即为反转后的链表

image-20220624213833873

var reverseList = function(head) {
    let pre = null
    let cur = head
    while(cur != null) {
        let nextNode = cur.next
        cur.next = pre
        pre = cur
        cur = nextNode
    }
    return pre
};

2.回文链表

image-20220624225014160

解法

1.双指针

思路

  1. 定义两个指针fast和slow,两指针均从链表的头结点出发,fast每次移动两个单位长度,slow每次移动一个单位长度
  2. fast移动到终点会出现两种情况:①fast最后刚好在链表的最后一个结点的话此时slow指针正好在链表的中间结点,那么就说明该链表长度为奇数;②fast最后指向了null的话,该链表长度为偶数;
  3. 如果链表长度为奇数,需要将slow指针从中间结点向后移动一位,使得slow指针的右侧链表长度小于左侧链表长度
  4. 然后反转右侧链表后将fast指针放在左侧链表的头结点,slow指针放在翻转后的右侧链表的头结点
  5. while(slow!=null)说明右侧链表没有遍历完,两指针同时向后移动一个单位,如果fast.val != slow.val则说明链表不是回文链表就返回false
  6. 直到slow == null就还没返回false则说明是回文链表,就返回true

image-20220624224431495

//用于链表翻转的方法
function reveseList(head) {
    let pre = null, cur = head
    while(cur != null) {
        let nextNode = cur.next
        cur.next = pre
        pre = cur
        cur = nextNode
    }
    return pre
}
var isPalindrome = function(head) {
    let fast = head, slow = head
    while(fast != null && fast.next != null) {
        fast = fast.next.next
        slow = slow.next
    }
    //当first为不为null但是first.next为null,说明该链表长度为奇数
    //此时slow处于链表正中间,需要将slow再往下移动一个单位,将中间结点赋给左侧链表
    if(fast != null) {
        slow = slow.next
    }
    //将右侧的链表进行反转
    slow = reveseList(slow)
    fast = head
    //此时slow是经反转后的链表
​
    //fast指针指向左侧链表的头结点,slow指针也指向右侧链表的头结点
    while(slow != null) {
        if(slow.val != fast.val) return false
        slow = slow.next
        fast = fast.next
    }
    return true
};