2. Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
python 解答
- 思路:
利用一个变量来控制进位,不断从两个链表中取数据到连接到新的链表当中。
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
add_num = 0
new_list = ListNode(0)
cur = new_list
cur1 = l1
cur2 = l2
while cur1 and cur2:
value = cur1.val + cur2.val + add_num
cur.next = ListNode(value%10)
add_num = 0
if value > 9:
add_num = 1
cur = cur.next
cur1 = cur1.next
cur2 = cur2.next
if cur1 == None and cur2 != None:
while cur2:
value = add_num + cur2.val
cur.next = ListNode(value%10)
add_num = 0
if value > 9:
add_num = 1
cur = cur.next
cur2 = cur2.next
if cur1 != None and cur2 == None:
while cur1:
value = add_num + cur1.val
cur.next = ListNode(value%10)
add_num = 0
if value > 9:
add_num = 1
cur = cur.next
cur1 = cur1.next
if cur1 == None and cur2 == None:
if add_num == 1:
cur.next = ListNode(add_num)
cur = cur.next
return new_list.next
- 思路二:
不需要分情况考虑,直接将所有的情况放在一个循环中进行操作。代码量虽然减少了,但是并没有减少空间和时间复杂度。
add_num = 0
new_list = ListNode(0)
cur = new_list
cur1 = l1
cur2 = l2
while cur1 or cur2:
if cur1 and cur2:
value = cur1.val + cur2.val + add_num
elif cur1:
value = cur1.val + add_num
elif cur2:
value = cur2.val + add_num
cur.next = ListNode(value % 10)
add_num = 0
if value > 9:
add_num = 1
cur = cur.next
if cur1:
cur1 = cur1.next
if cur2:
cur2 = cur2.next
if cur1 == None and cur2 == None and add_num:
cur.next = ListNode(add_num)
cur = cur.next
return new_list.next
23. Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
python 解答:
- 思路: 先将所有节点放在一个list中,之后使用归并排序进行排序后连接成新的链表
不过一直显示我超出时间限制,感觉用的时间不会太长呀。。。
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
def mergesort(lists):
length = len(lists)
if length < 2:
return lists
middle = int(math.floor(length / 2))
# print(middle)
left = lists[ :middle]
right= lists[middle: ]
return merge(mergesort(left), mergesort(right))
def merge(left, right):
result = []
len_left = len(left)
len_right = len(right)
i = j = 0
while i<len_left and j<len_right:
if left[i].val >= right[j].val:
result.append(right[j])
j += 1
elif left[i].val < right[j].val:
result.append(left[i])
i += 1
if i == len_left and len_right > j:
for k in right[j:]:
result.append(k)
# result.append(right[j:])
if i < len_left and len_right == j:
for m in left[i:]:
result.append(m)
# result.append(left[i:])
return result
# dict1 = dict()
if len(lists) == 0:
return None
list_1 = []
i = 0
for list_node in lists:
if list_node == None:
continue
cur = list_node
while cur:
# dict1[cur] = cur.val
list_1.append(cur)
cur = cur.next
result = mergesort(list_1)
# for value in result:
# print(value.val)
for i in range(len(result)-1):
result[i].next = result[i+1]
if len(result) == 0:
return None
return result[0]
- 采用了python自带的sort发现效果很好,以后碰到排序还是直接用python自带的吧。。
def take_val(node):
return node.val
if len(lists) == 0:
return None
result = []
i = 0
for list_node in lists:
if list_node == None:
continue
cur = list_node
while cur:
# dict1[cur] = cur.val
result.append(cur)
cur = cur.next
result.sort(key=take_val)
# for value in list_1:
# print(value.val)
for i in range(len(result)-1):
result[i].next = result[i+1]
if len(result) == 0:
return None
return result[0]
86. Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
Example:
Input: head = 1->4->3->2->5->2, x = 3
Output: 1->2->2->4->3->5
-
思路
建立两个链表,将小的放在less_head中,大的放在more_head中,最后合并两个链表 -
解答
class Solution(object):
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
less_head = ListNode(0)
more_head = ListNode(0)
cur = head
cur_less = less_head
cur_more = more_head
while cur:
if cur.val < x:
cur_less.next = cur
cur = cur.next
cur_less = cur_less.next
else:
cur_more.next = cur
cur = cur.next
cur_more = cur_more.next
cur_more.next = None
cur_less.next = more_head.next
return less_head.next
142. Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
题目描述的有点问题,返回的应该是环的初始地址而不是初始地址的index
- 思路一:
使用set合集,head地址存放到set中,如果发现了set中有相同的地址则说明有环并输出地址。
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
d = set()
cur = head
i = 0
while cur:
# print(cur.val)
if cur in d:
return cur
d.add(cur)
# i += 1
cur = cur.next
return None
- 思路二:
解题思路:分两个步骤,首先通过快慢指针的方法判断链表是否有环;接下来如果有环,则寻找入环的第一个节点。具体的方法为,首先假定链表起点到入环的第一个节点A的长度为a【未知】,到快慢指针相遇的节点B的长度为(a + b)【这个长度是已知的】。现在我们想知道a的值,注意到快指针p2始终是慢指针p走过长度的2倍,所以慢指针p从B继续走(a + b)又能回到B点,如果只走a个长度就能回到节点A。但是a的值是不知道的,解决思路是曲线救国,注意到起点到A的长度是a,那么可以用一个从起点开始的新指针q和从节点B开始的慢指针p同步走,相遇的地方必然是入环的第一个节点A。 文字有点绕,画个图就一目了然了
fast = head
slow = head
while fast != None and fast.next != None:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
if fast == None or fast.next == None:
return None
while head != slow:
head = head.next
slow = slow.next
return head
138. Copy List with Random Pointer
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
python实现:
- 思路
方法一: 将label和random分别按照顺序保存在两个dict中,之后进行遍历和连接
if head == None:
return None
cur = head
i = 0
d1 = dict()
d2 = dict()
while cur:
d1[cur] = i
d2[i] = RandomListNode(cur.label)
i += 1
cur = cur.next
d2[i] = RandomListNode(0)
cur = head
i = 0
while cur:
print(d2[i].label)
d2[i].next = d2[i+1]
if cur.random == None:
cur = cur.next
i += 1
continue
id1 = d1[cur.random]
d2[i].random = d2[id1]
cur = cur.next
i += 1
cur = d2[0]
while cur.next.next:
cur = cur.next
cur.next = None
return d2[0]
- 方法二: 思想和方法一一样,改进方法是利用了迭代器,更简单明了一些,使用迭代器连接node,然后random能够索引到指定节点的位置。
if head == None:
return None
def fun(cur):
while cur:
yield(cur, RandomListNode(cur.label))
cur = cur.next
dict1 = {k:v for k, v in fun(head)}
cur = head
for k, v in dict1.items():
if k.next:
v.next = dict1[k.next]
if k.random:
v.random = dict1[k.random]
return dict1[head]
21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
- 解题思路
新建一个表头,当两个链表都有的时候按照大小进行排序添加到表头的尾部,到其中一个链表为空时则插入另一个链表的剩余部分。
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
cur1 = l1
cur2 = l2
head = ListNode(0)
cur3 = head
while cur1 and cur2:
if cur1.val <= cur2.val:
cur3.next = cur1
cur3 = cur3.next
cur1 = cur1.next
elif cur1.val > cur2.val:
cur3.next = cur2
cur3 = cur3.next
cur2 = cur2.next
if cur1 == None and cur2 != None:
cur3.next = cur2
elif cur1 != None and cur2 == None:
cur3.next = cur1
return head.next