编程导航算法通关村第 1 关 | 白银教程 | 回文链表检查

题目要求:检查链表是否回文

示例

输入: 1->2->2->1
输出: true
  • 基本方法:将链表元素全部压栈,然后一边出栈,一边重新遍历链表,一边比较两者元素值,只要有一个不相等,那就不是。
def isPalindrome(self, head):
        cur, length = head, 0
        result = []
        # 遍历链表,把所有节点上的元素都存储到列表 result 中
        while cur is not None:
            length += 1
            result.append(cur.val)
            cur = cur.next
        # 定义2个指针,一个从头开始往后,另一个从最后开始往前
        left, right = 0, length - 1
        while left < right:
            if result[left] != result[right]:
                return False
            left += 1
            right -= 1
        return True
  • 优化方法:先遍历第一遍,得到总长度。之后一边遍历链表,一边压栈。到达链表长度一半后就不再压栈,而是一边出栈,一边遍历,一边比较,只要有一个不相等,就不是回文链表。这样可以节省一半的空间。
def isPalindrome(self, head):
        cur, length = head, 0
        result = []
        # 遍历链表,得到总长度
        while cur is not None:
            length += 1
            cur = cur.next
        # 遍历链表,把一半节点上的元素都存储到列表 result 中
        while (length-1)/2 > 0:
            result.append(cur.val)
            cur = cur.next
            (length-1)/2 -= 1
        # 定义2个指针,一个从头开始往后,另一个从一半最后开始往前
        left, right = 0, (length-1)/2 - 1
        while left < right:
            if result[left] != result[right]:
                return False
            left += 1
            right -= 1
        return True
  • 继续优化:既然要得到长度,那还是要遍历一次链表才可以,那是不是可以一边遍历一边全部压栈,然后第二遍比较的时候,只比较一半的元素呢?也就是只有一半的元素出栈, 链表也只遍历一半,当然可以。
def isPalindrome(self, head):
        cur, length = head, 0
        result = []
        # 遍历链表,把所有节点上的元素都存储到列表 result 中
        while cur is not None:
            length += 1
            result.append(cur.val)
            cur = cur.next
        # 定义2个指针,一个从头开始往后,另一个从一半最后开始往前
        left, right = 0, (length-1)/2 - 1
        while left < right:
            if result[left] != result[right]:
                return False
            left += 1
            right -= 1
        return True
  • 高级方法:反转链表法, 先创建一个链表newList,将原始链表oldList的元素值逆序保存到newList中,然后重新一边遍历两个链表,一遍比较元素的值,只要有一个位置的元素值不一样,就不是回文链表。
def isPalindrome(self, head):
        cur1, cur2, length = head, 0, 0
        oldList = []
        newList = []
        # 遍历链表,把所有节点上的元素都存储到原列表中
        while cur1 is not None:
            length += 1
            oldList.append(cur1.val)
            cur1 = cur1.next
        # 逆序遍历,将原链表逆向保存到新链表中
        while length - 1 > 0:
            newList[cur2] = oldList[length - 1]
            cur2 += 1
            length -= 1
        # 重新遍历比较
        pointer = 0
        while pointer < length - 1:
            if oldList[pointer] != newList[pointer]:
                return False
            pointer += 1
        return True
  • 再次优化:我们只反转一半的元素就行了。先遍历一遍,得到总长度。然后重新遍历,到达一半的位置后不再反转,就开始比较两个链表。
def isPalindrome(self, head):
        cur1, cur2, length = head, 0, 0
        oldList = []
        newList = []
        # 遍历链表,把所有节点上的元素都存储到原列表中
        while cur1 is not None:
            length += 1
            oldList.append(cur1.val)
            cur1 = cur1.next
        # 逆序遍历,将原链表逆向保存一半到新链表中
        while (length - 1)/2 > 0:
            newList[cur2] = oldList[(length - 1)/2]
            cur2 += 1
            (length-1)/2 -= 1
        # 重新遍历比较一半
        pointer = 0
        while pointer < (length - 1)/2:
            if oldList[pointer] != newList[pointer]:
                return False
            pointer += 1
        return True

你可能感兴趣的:(算法,链表,数据结构)