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:
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:
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):