美文网首页算法学习
算法题--单向链表局部翻转

算法题--单向链表局部翻转

作者: 岁月如歌2020 | 来源:发表于2020-04-26 16:59 被阅读0次
image.png

0. 链接

题目链接

1. 题目

Reverse a linked list from position m to n. Do it in one-pass.

Note: 1 ≤ m ≤ n ≤ length of list.

Example:

Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL

2. 思路1:双指针法

  • 单向链表,又是局部翻转, 要求单次遍历得到结果,所以需要两个指针left和right
  • 除了两个指针负责前进+翻转外,还需要一个指针left_last来记录翻转起始点,用来收拢翻转后的结果
  • 具体过程:
left_last开始位置在head之左,
left_last=ListNode(-1), 
left_last.next=head, 
left=head, right=head.next

然后从左到右遍历, 记录遍历过的元素数 count

  • 当count < m时, last_left需要记录一下left, left,right需要向右移1位
  • 当m <= count < n时, last_left保持不动, 需要通过left和right进行指针转向, 转向后, left和right都向右平移1位
  • 当 count == n时, 结束点确定为left, 而right就变成区间右边的第一个元素, 此时只需要将last_left的next指向left当前位置, 而last_left.next.next指向right当前位置, 这样就将链表又合并为一个整体了

关于返回值,分两种情况

  • m = 1时, head发生了变化, left_last.next指向当前head, 返回left_last.next即可
  • m > 1时, head没有发生变化, 直接返回head即可

3. 代码

# coding:utf8


# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        left_last = ListNode(-1)
        left_last.next = head
        left = head
        right = head.next
        count = 0
        while True:
            count += 1
            if count < m:
                left_last = left
                left = left.next
                right = right.next
            elif count < n:
                temp = right.next
                right.next = left
                left = right
                right = temp
            else:
                left_last.next.next = right
                left_last.next = left
                break

        return left_last.next if m == 1 else head


def array_to_linked_list(array):
    head = node = ListNode(-1)
    for each in array:
        node.next = ListNode(each)
        node = node.next
    return head.next


def linked_list_to_array(head):
    array = list()
    while head is not None:
        array.append(head.val)
        head = head.next
    return array


def print_linked_list(head):
    print('->'.join([str(x) for x in linked_list_to_array(head)]))


def my_test(solution, array, m, n):
    head = array_to_linked_list(array)
    print('input: ')
    print_linked_list(head)
    print('m = {}, n = {}'.format(m, n))
    print('output: ')
    print_linked_list(solution.reverseBetween(head, m, n))
    print('=' * 50)
    print('')


solution = Solution()
my_test(solution, [1, 2, 3, 4, 5], 1, 3)
my_test(solution, [3, 5], 1, 2)

输出结果

input: 
1->2->3->4->5
m = 1, n = 3
output: 
3->2->1->4->5
==================================================

input: 
3->5
m = 1, n = 2
output: 
5->3
==================================================

4. 结果

image.png

相关文章

网友评论

    本文标题:算法题--单向链表局部翻转

    本文链接:https://www.haomeiwen.com/subject/iodjwhtx.html