Esempio n. 1
0
from typing import List
from my_data_structure import generate_linknode_from_list, print_linknode, LinkNode as ListNode
tcs = [
    (generate_linknode_from_list([1, 2, 3, 3, 2, 0]),),
    (generate_linknode_from_list([1, 2, 3, 4, 3, 2, 1]),),
    (generate_linknode_from_list([1]),),
    (generate_linknode_from_list([1, 2]),),
]


class Solution:
    # 方法1:快慢指针+倒转
    def isPalindrome(self, head: ListNode) -> bool:
        if not head:
            return True
        p, last_node, p2 = head, None, head
        while p2 and p2.next and p2.next.next:
            p2 = p2.next.next
            p.next, p, last_node = last_node, p.next, p
        # 如果快指针不是停在最后,说明有偶数个节点,这时p在左半边上,需要让p再往前操作一步,否则左边少一个。
        # 如果快指针停在了最后,说明有奇数个节点,这时p正好在中间节点上,不需要操作。
        if p2.next:
            p.next, p, last_node = last_node, p.next, p
        # 如果是奇数个,p停在了中间节点,需要右移一下
        else:
            p = p.next

        # 经过快慢指针的操作,保证最后last_node停在已经反转的左半边的头结点上,p则是右半边的头结点。此时只需要对比这两个子链表是否一致即可。
        # print_linknode(last_node)
        # print_linknode(p)
        while p:
Esempio n. 2
0
from my_data_structure import generate_linknode_from_list, print_linknode, linknode_add_circle, LinkNode

# 有环
# 入口在中间
tc = linknode_add_circle(generate_linknode_from_list([1, 2, 3, 4, 5, 6, 7]), 4)
# 入口在末尾(尾巴节点不能连接自己)
tc = linknode_add_circle(generate_linknode_from_list([1, 2, 3, 4, 5, 6, 7]), 6)
# 入口在开头
tc = linknode_add_circle(generate_linknode_from_list([1, 2, 3, 4, 5, 6, 7]), 1)

# 无环
tc = generate_linknode_from_list([1, 2, 3])
tc = generate_linknode_from_list([1])


def main(linknode):
    inside_counter = set()
    while linknode:
        if linknode in inside_counter:
            return linknode
        inside_counter.add(linknode)
        linknode = linknode.next
    return '该单向链表没有环'


if __name__ == '__main__':
    res = main(tc)
    if type(res) == LinkNode:
        print(res.val)
    else:
        print(res)
from my_data_structure import generate_linknode_from_list, print_linknode

# 普通测试用例
tc = generate_linknode_from_list([1, 2, 3, 3, 4, 4, 5, 6])
# 头重复
tc = generate_linknode_from_list([1, 1, 2, 3, 4, 4, 5])
# 尾重复
tc = generate_linknode_from_list([1, 2, 3, 4, 4])
# 两位不重复
tc = generate_linknode_from_list([1, 2])
# 两位重复
tc = generate_linknode_from_list([1, 1])
# 单节点
tc = generate_linknode_from_list([1])
# 全部是都是重复的
tc = generate_linknode_from_list([1, 1, 1, 1, 1, 1])


def main(head):
    # 只有一个节点的链表,不需要去重
    if not head.next:
        return head

    # 得到不重复的头结点
    def set_real_head(head):
        """
        找到第一个非重复的节点作为结果的头结点\n
        输入链表的长度大于1\n
        return None:全是重复的,LinkNode:第一个不和后面重复的节点\n
        """
        while head:
Esempio n. 4
0
from typing import List
from my_data_structure import generate_linknode_from_list, print_linknode
from my_data_structure import LinkNode as ListNode
tcs = [
    (generate_linknode_from_list([1, 2, 3, 4, 5, 6]), 6),
]


class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        last_node = None
        pointer = head
        to_delete = None
        while pointer:
            if eval('pointer' + '.next' * n) is None:
                to_delete = pointer
                break
            else:
                last_node = pointer
                pointer = pointer.next
        # 要删的是头结点
        if not last_node:
            return head.next
        # 要删的是尾节点
        if not to_delete.next:
            last_node.next = None
            return head
        # 要删的是中间节点
        last_node.next = to_delete.next
        to_delete.next = None
        return head
from my_data_structure import generate_linknode_from_list, print_linknode

# 每隔K个反转链表
# 关键问题:一边遍历一边修改的话,会影响遍历。
tc = [
    generate_linknode_from_list([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
    generate_linknode_from_list(list(range(1))),
]


# 解决:先遍历,将要修改next的节点成对放到元组里。遍历完成后再批量修改
# 这种方法要求k>1。k=1时失效。k=1则退化成了反转单项链表的问题
def main(linknode, k):
    # 先对要修改next指针的节点进行配对,放进元组中。
    pairs = list()
    last_head = list()
    new_tail_found = False
    counter = 1
    while linknode:
        if counter % k == 1:
            last_head.append(linknode)
        elif counter % k == 0:
            if not new_tail_found:
                this_pair = (linknode, None)
                new_tail_found = True
            else:
                this_pair = (linknode, last_head.pop(0))
            pairs.append(this_pair)
        elif not linknode.next:
            pairs.append((linknode, last_head.pop(0)))
        counter += 1
from my_data_structure import generate_random_linknode, print_linknode, get_random_node, generate_linknode_from_list, get_specific_linknode

# 正常测试用例
tc = generate_random_linknode(10, 3)
tc_del = get_random_node(tc)
print('原始单项链表为:')
print_linknode(tc)
print('要删除的节点为:')
print_linknode(tc_del)

# 删除尾巴节点
tc = generate_linknode_from_list([1, 2, 3, 4, 5])
tc_del = get_specific_linknode(tc, 5)
print('原始单项链表为:')
print_linknode(tc)
print('要删除的节点为:')
print_linknode(tc_del)

# 只有一个节点的单项链表删除节点
tc = generate_linknode_from_list([1])
tc_del = get_specific_linknode(tc, 1)
print('原始单项链表为:')
print_linknode(tc)
print('要删除的节点为:')
print_linknode(tc_del)

# 正常删除需要找到要删除节点的上一个节点,需要遍历。
# 所以为了实现O1复杂度的删除,要在下一个节点做手脚:用待删除节点的下一个节点覆盖掉待删除节点即可。


def main(head, del_node):