15. 3Sum
Description
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路及代码
题目要求求解三个数的和为0的数的所有组合,当给定数组元素个数小于3时,没有返回结果。在其他情况下,先将数组排序,然后遍历数组,从当前位置的下一个位置和数组最后一个元素开始分别向后和向前遍历,计算三个数的和,如果和等于0,将三个数存进结果数组,然后接着计算,如果遇到重复的元素直接跳过,当指向后一个元素的指针指向的元素等于指向前一个元素的指针指向的元素时,内层循环结束。对应的Python代码如下:
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if len(nums) < 3:
return
nums.sort()
result = []
for i in range(len(nums)):
if i == 0 or nums[i] > nums[i - 1]:
j, k = i + 1, len(nums) - 1
while j < k:
s = nums[j] + nums[k] + nums[i]
if s == 0:
result.append([nums[i], nums[j], nums[k]])
j += 1
k -= 1
while j < k and nums[j] == nums[j - 1]:
j += 1
while k > 1 and nums[k] == nums[k + 1]:
k -= 1
elif s > 0:
k -= 1
else:
j += 1
return result
21. Merge Two Sorted Lists
Description
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
思路及代码
合并两个有序链表,这里申请一个新的链表结点,然后分别遍历两个链表,当两个链表都不为空的时候,如果l1的值小于l2的值,新的结点指向l1的当前值,l1指针向后移动;否则新的结点指向l2的当前结点,l2指针向后移动。跳出当前循环后,判断l1和l2是否为空,不为空则将剩下的部分并入新的链表。对应的Python代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1:
return l2
if not l2:
return l1
newNode = ListNode(0)
head = newNode
while l1 and l2:
if l1.val < l2.val:
head.next = l1
l1 = l1.next
else:
head.next = l2
l2 = l2.next
head = head.next
if l1:
head.next = l1
if l2:
head.next = l2
return newNode.next
23. Merge k Sorted Lists
Description
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代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
def mergeTwoLists(l1, l2):
if not l1: return l2
if not l2: return l1
newNode = ListNode(0)
head = newNode
while l1 and l2:
if l1.val < l2.val:
head.next = l1
l1 = l1.next
else:
head.next = l2
l2 = l2.next
head = head.next
if l1:
head.next = l1
if l2:
head.next = l2
return newNode.next
if len(lists) == 0:
return None
n = len(lists)
res = lists[0]
for i in range(1, n):
res = mergeTwoLists(res, lists[i])
return res
当然了这种方法的效率很低,运行时间和占用内存都比较多。
Runtime: 4256 ms, faster than 10.41% of Python online submissions for Merge k Sorted Lists.
Memory Usage: 17.3 MB, less than 98.28% of Python online submissions for Merge k Sorted Lists.
- 第二种方法:上面借鉴了合并两个有序链表的函数,但是由于需要多次调用合并两个链表的函数,执行的时间比较长,而堆可以用于合并多个有序小文件,所以第二种方法用堆的方法求解,使用Python自带的堆函数。创建一个小顶堆,然后堆顶存储链表的头结点对应的值和链表在输入数组中的下标,将所有的链表存储进小顶堆后,再遍历小顶堆,通过不断弹出堆顶元素,将弹出的堆顶结点添加到新链表后面,更新小顶堆,完成有序链表的合并。对应的Python代码如下。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
head = l = ListNode(0)
heap = []
for i in range(len(lists)):
if(lists[i]):
heapq.heappush(heap, [lists[i].val,i])
while(heap):
cur = heapq.heappop(heap)[1]
l.next = lists[cur]
l = l.next
lists[cur] = lists[cur].next
if(lists[cur]):
heapq.heappush(heap, [lists[cur].val, cur])
return head.next
Runtime: 84 ms, faster than 80.13% of Python online submissions for Merge k Sorted Lists.
Memory Usage: 17.4 MB, less than 84.11% of Python online submissions for Merge k Sorted Lists.