defadd_to_index(head,index,value):#head: type node, the first node of the passed singly linked list#index: type int, the position where you want to insert (starting from 0)#value: type *, the value that will be referred by the newly added list node object if our operation is successful#return: 必须返回一个头节点(修改后的链表的头节点),不然找不见list,也不知道这个function是否成功了if index ==0: new_head =ListNode(value) new_head.next = headreturn new_headelse: prevNode =search_by_index(head, index-1)if prevNode isNone:return head new_node =ListNode(value) new_node.next = prevNode.next prevNode.next = new_nodereturn head
为了add a new node,其实不能直接走到index,而是要走到index-1的位置,因为单链表只能往后走,不能往前走。但是很棘手的是,头节点没有index-1. 所以定义一个new_head,这也是如果我们改动了头节点然后返回的。
defremove_from_index (head,index):# validity check is implicit, in search_by_index function# find the node with a reference of index# return the fake_head fake_head =ListNode(None) fake_head.next = head prev_node =search_by_index(fake_head, index)if prev_node isNoneor prev_node.next isNone:# it is likely that we find the prev of the node, but not the node itselfreturn fake_head.next remove_node = prev_node.next prev_node.next = remove_node.next remove_node.next =None#or don't write anythingreturn fake_head.next
classSolution(object):defnumberOfNodes(self,head):""" input: ListNode head return: int """# write your solution here steps =0while head: steps+=1 head=head.nextreturn steps
How to design a linked list class
class_ListNode(object):def__init__(self,val): self.value = val self.next =NoneclassMyLinkedList(object):def__init__(self):#一般不是从状态开始想起,而是想,它能实现什么样的功能,再在class中实现这些功能 这叫实现 是实现的一部分 我们一般不希望用户看到实现的一部分,而只是希望用户看到接口是什么# we should have a reference that ALWAYS points to the first node of the internally maintained singly linked list self._head =None#逻辑上的实现,这里None说得过去(区分下面的)永远maitain一个指向单链表的头节点 self._tail =None#永远指向单链表最后一个元素 self._size =0#永远表示 # of nodes in the listdef_get(self,index): # return the node we found, 区分于下面的这个# assume index is valid. node = self._head #不然就会破坏上面的ALWAYSfor _ inxrange(index): node = node.nextreturn nodedefget(self,index): #instance method or object method 调用这些方法一定要通过对象来调用 free function就不用self(写在class外面的不用)#返回第index个node的node value# How do we know the index is out of range?if index <0or index >=self._size:return-1return self._get(index).valuedefaddAtHead(self,index,val):#如果一个链表只有一个节点,它既是头节点,又是尾节点if size._size ==0: self._head = self._tail =_ListNode(val) self._size +=1else: new_head =_ListNode(val) new_head.next = self._head #新的头节点的后面应该是原来的头节点 self._head = new_head self._size +=1defaddAtTail(self,val):# 需要先判断现在的链表是不是空的,不然默认tail是None 就没办法.next了if size._size ==0: self._head = self._tail =_ListNode(val) self._size +=1else: self._tail.next =_ListNode(val) self._tail = self._tail.next self._size +=1defaddAtIndex(self,index,val):defdeleteAtIndex(self,index):if index <0or index>= self._size:returnif index==0: self._head = self._head.next self._size -=1# 如果remove掉的就是原来链表的最后一个 if self._size ==0: self.tail =Noneelse: node = self._get(index-1) node.next=node.next.next# 如果remove掉的就是原来链表的tailif index=self._size -1: self._tail=node self._size -=1ll =MyLinkedList()# We should have an empty linked list after initialization (not None) 容积在,只是容器是空的
One sentence high-level description of the problem
Do a linear scan on each element, move next pointer to the previous element
Clarification of the problem assumptions
Data Structure (物理意义 or semantic) 不变的关系
curr: the node which I want to change its next to its previous node
prev: curr's previous node in the input linkedlist
next: curr's next node in the input linkedlist
classSolution(object):defreverse(self,head):""" input: ListNode head return: ListNode """# write your solution here prev, curr =None, headwhile curr:next=curr.next ##preserve the next pointer since we are changing it afterwards curr.next=prev prev=curr curr=nextreturn prev
defreverse (head): #reverse the linkedlist headed by headif head isNoneor head.next isNone:# linked list is empty or contains only one nodereturn head node =reverse(head.next)# 当前head的头节点就是所反转list的尾节点 在执行完head.next这一行之后,head.next的值还是原来的 tail = head.next tal.next = head head.next =Nonereturn nodeclassSolution(object):defreverse(self,head):""" input: ListNode head return: ListNode """# write your solution hereifnot head ornot head.next:return head newhead = self.reverse(head.next) head.next.next=head head.next=Nonereturn newhead
Reverse Linked List in Pairs
Reverse pairs of elements in a singly-linked list.
Examples
L = null, after reverse is null
L = 1 -> null, after reverse is 1 -> null
L = 1 -> 2 -> null, after reverse is 2 -> 1 -> null
L = 1 -> 2 -> 3 -> null, after reverse is 2 -> 1 -> 3 -> null
classSolution(object):defremoveNthFromEnd(self,head,n):""" input: ListNode head, int n return: ListNode """# write your solution here dummyHead=ListNode('dummy') dummyHead.next=head curr,fast=dummyHead,dummyHeadwhile n>0and fast: fast=fast.next n-=1ifnot fast:return dummyHead.nextwhile fast and fast.next: fast=fast.next curr=curr.next curr.next=curr.next.nextreturn dummyHead.next
Partition a Linked List
Given a linked list and a target value T, partition it such that all nodes less than T are listed before the nodes larger than or equal to target value T. The original relative order of the nodes in each of the two partitions should be preserved.
Examples
L = 2 -> 4 -> 3 -> 5 -> 1 -> null, T = 3, is partitioned to 2 -> 1 -> 4 -> 3 -> 5 -> null
Assumption:
- < 和 >=
- Duplication
- Integer
Data Structure
- dummyHeadSmall smallTail
- dummyHeadLarge LargeTail
最后一定记得把largetail的尾巴断了
classSolution(object):defpartition(self,head,target):""" input: ListNode head, int target return: ListNode """# write your solution here dummyHeads=ListNode('Small') tails = dummyHeads dummyHeadl=ListNode('Large') taill = dummyHeadl curr=headwhile head:if head.val<target: tails.next=head tails=tails.nextelse: taill.next=head taill=taill.next head = head.next tails.next=dummyHeadl.next taill.next=None#最后一定记得把largetail的尾巴断了 不然就是一个loop了return dummyHeads.next
Add two linked list which represents large number
大数:传统语言int long的范围是 232 范围之外称为大数
在Python里自动支持大数,转化好了
如何靠右对齐,个位对齐? Reverse
进位 carry
两个linkedlist不等长 所以注意while循环的break,post-processing
reverse最后的结果
这个题目是已经reverse过了的 所以不需要reverse function
classSolution(object):defaddTwoNumbers(self,l1,l2):""" input: ListNode l1, ListNode l2 return: ListNode """# write your solution here dummyHead =ListNode('dummy') tail=dummyHead curr =0while l1 or l2 or curr!=0:if l1: curr += l1.val l1=l1.nextif l2: curr += l2.val l2=l2.next tail.next=ListNode(curr%10) tail=tail.next curr = curr//10return dummyHead.next
classSolution(object):defmiddleNode(self,head):""" input: ListNode head return: ListNode """# write your solution hereifnot head ornot head.next:return head slow,fast=head,headwhile fast.next and fast.next.next: slow=slow.next fast=fast.next.nextreturn slow
data structure: slow and fast, fast之前包含fast的节点个数=2*slow之前包含slow的节点个数
initialization:slow=head, fast=head.next
classSolution(object):defmiddleNode(self,head):""" input: ListNode head return: ListNode """# write your solution here# # of node on the left of fast = 2* # of node on the left of slow (including)ifnot head ornot head.next:return head slow, fast = head, head.nextwhile fast and fast.next: slow=slow.next fast=fast.next.nextreturn slow
Clarification
- ascending or descending
- data type: integer
- what to do when there is duplication:
Data Structure:
DummyHead
curr1
curr2
curr
dummyHead:
(1) When we need to change the head / when the headNode might be changed
(2) When we need to build a new Linked List from scratch (from 0 node)
dummyTail:
When we need to expand elements from the end of the Linked List.
classSolution(object):defmerge(self,one,two):""" input: ListNode one, ListNode two return: ListNode """# write your solution here dummyHead=ListNode('dummy') tail = dummyHead curr1, curr2 = one, twowhile curr1 and curr2:if curr1.val<=curr2.val: tail.next=curr1 curr1=curr1.nextelse: tail.next=curr2 curr2=curr2.next tail = tail.next tail.next = curr1 if curr1 else curr2return dummyHead.next
ReOrder Linked List
Reorder the given singly-linked list N1 -> N2 -> N3 -> N4 -> … -> Nn -> null to be N1- > Nn -> N2 -> Nn-1 -> N3 -> Nn-2 -> … -> null
Examples
L = null, is reordered to null
L = 1 -> null, is reordered to 1 -> null
L = 1 -> 2 -> 3 -> 4 -> null, is reordered to 1 -> 4 -> 2 -> 3 -> null
L = 1 -> 2 -> 3 -> null, is reordred to 1 -> 3 -> 2 -> null
Step 1: Find Mid and Split to 2 Linked List
Step 2: Reverse the second Linked List
Step 3: Merge the two Linked List
classSolution(object):defreorder(self,head):""" input: ListNode head return: ListNode """# write your solution hereifnot head ornot head.next:return head mid = self.findmid(head) head1 = head head2 = mid.next mid.next =None head2 = self.reverse(head2) newhead = self.merge(head1, head2)return newheaddeffindmid(self,head): slow, fast = head, head.nextwhile fast and fast.next: slow=slow.next fast=fast.next.nextreturn slowdefreverse(self,head):ifnot head ornot head.next:return head newhead = self.reverse(head.next) head.next.next=head head.next=Nonereturn newheaddefmerge(self,head1,head2): dummyHead=ListNode('dummy') tail=dummyHeadwhile head1 and head2: tail.next=head1 head1=head1.next #注意这一行和下一行不能换位置 要先让h1脱险 tail.next.next=head2 head2=head2.next tail=tail.next.next tail.next = head1 if head1 else head2return dummyHead.next
Merge Sort Linked List
classSolution(object):defmergeSort(self,head):""" input: ListNode head return: ListNode """# write your solution hereifnot head ornot head.next:return head mid = self.findmid(head) head1, head2 = head, mid.next mid.next =None left = self.mergeSort(head1) right = self.mergeSort(head2)return self.merge(left, right)deffindmid(self,head):ifnot head ornot head.next:return head slow, fast = head, head.nextwhile fast and fast.next: slow=slow.next fast=fast.next.nextreturn slowdefmerge(self,head1,head2): dummyHead =ListNode('dummy') tail = dummyHeadwhile head1 and head2:if head1.val<head2.val: tail.next=head1 head1=head1.nextelse: tail.next=head2 head2=head2.next tail=tail.next tail.next=head1 if head1 else head2return dummyHead.next
链表、环的问题
Check if linkedlist has cycle
这里可以不需要一开始的sanity check
classSolution(object):defcheckCycle(self,head):""" input: ListNode head return: boolean """# write your solution here# if not head:# return False slow, fast = head, headwhile fast and fast.next: slow=slow.next fast=fast.next.nextif fast==slow:returnTruereturnFalse