21. Merge Two Sorted Lists
方法:linked list
Merge two sorted linked lists and return it as a new sorted list. The new list should be made by splicing together the nodes of the first two lists.
Example 1:
Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4,4]
Example 2:
Input: l1 = [], l2 = []
Output: []
Example 3:
Input: l1 = [], l2 = [0]
Output: [0]
Constraints:
- The number of nodes in both lists is in the range
[0, 50]
. -100 <= Node.val <= 100
- Both
l1
andl2
are sorted in non-decreasing order.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
temp = ListNode(1) # a temp pointer to store start position
l3 = temp # a pointer to store each elemnet
while l1 and l2: # if both have element. store the sorted value
if l1.val < l2.val:
l3.next = l1 # store the element pointedd by l1
l1 = l1.next # shift l1
else:
l3.next = l2 # # store the element pointedd by l2
l2 = l2.next # shift l2
l3 = l3.next # shift l3
l3.next = l1 or l2 # stored the rest element
return temp.next
-
step 1:
- initialize, l1 = NodeList(1), l1.next = NodeList(2), l1.next.next = NodeList(4)
- l2= NodeList(1), l2.next = NodeList(3), l2.next.next = NodeList(4)
- l3 = temp = ListNode(1), can be any value
-
step 2:
- l2.val <= l1.val
- l3.next = l2
- l2 = l2.next
- l3 = l3.next
-
other steps: the same as before
JS:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
let temp = new ListNode();
let l3 = temp;
while (l1 && l2) {
if (l1.val < l2.val) {
l3.next = l1;
l1 = l1.next;
} else {
l3.next = l2;
l2 = l2.next;
}
l3 = l3.next;
}
l3.next = l1 || l2;
return temp.next;
};
22. Generate Parentheses
方法: stack
1 遇到括号,按照栈来处理,因为括号的匹配一定是成对的,只有栈才可以得到有效括号,如果需要列举,就用到dfs收索。本题dfs就是二叉树的递归调用,并满足有效括号的输出。
函数在内存中是按照栈的形式存储,如果 n = 1,实际函数的执行如下:
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
stack = []
res = []
def backTrack(openN, closedN): # openN, closedN = 0, 0
if openN == closedN == n: # n = 1
res.append(''.join(stack))
if openN < n: # openN = 0, n = 1
stack.append('(') # stack = ['(']
# backTrack(openN+1, closedN): # # openN, closedN = 1, 0
if openN == closedN == n: # openN, closedN = 1, 0, n = 1, not execute
res.append(''.join(stack))
if openN < n: # openN = 1, n = 1, not execute
stack.append('(')
backTrack(openN+1, closedN)
stack.pop()
if closedN < openN: # closeN = 0, n = 1, execute
stack.append(')') # stack = ['(', ')']
# backTrack(openN, closedN+1)
if openN == closedN == n: # openN == closedN = 1, n = 1
res.append(''.join(stack)) # res = ['()']
if openN < n: # openN = 1, n = 1 not execute
stack.append('(')
backTrack(openN+1, closedN)
stack.pop()
if closedN < openN: # closedN = 1, openN = 1, not execute
stack.append(')')
backTrack(openN, closedN+1)
stack.pop()
stack.pop() # stack = ['('], execute
stack.pop() # stack = [], execute
if closedN < openN: # closedN = 1, openN = 1, not execute
stack.append(')')
backTrack(openN, closedN+1)
stack.pop()
backTrack(0, 0) # above
return res # res = ['()']
这样相当于至上而下执行代码。执行完之后栈空,继续在寻找下一个。当全部不满足是推出。
实际代码如下:
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
stack = []
res = []
def backTrack(openN, closedN):
if openN == closedN == n:
res.append(''.join(stack))
if openN < n:
stack.append('(')
backTrack(openN + 1, closedN)
stack.pop()
if closedN < openN:
stack.append(')')
backTrack(openN, closedN + 1)
stack.pop()
backTrack(0, 0)
return res
1 if openN < n: 表示入栈的顺序
2 if closedN < openN:得到有效的括号。
3 stack.pop():最后的栈空
4 if openN == closedN == n: 输出每一个结果。
23. Merge k Sorted Lists
方法:优先队列
这里需要注意heapq的引入,因为leetcode版本默认import, 但是在其他的IDE上需要:import heapq
heapq是对的意思, 最常用的是最为优先队列,是目前最好的方法。
可以大大降低时间。
如果无法本地运行,需要 import heapq 防止ide没有import。
method: pq
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
# pq
pq = []
q = dummy = ListNode(0)
for item in lists:
p = item
while p:
heapq.heappush(pq, p.val) # keep min heap
p = p.next
while pq:
val = heapq.heappop(pq) # min number
q.next = ListNode(val)
q = q.next
return dummy.next
24. Swap Nodes in Pairs
method: linked list
这种题很难,只能多做练习,指针的操作需要满足成对的置换,然后移动
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
prev = dummy = ListNode(0)
dummy.next = head
curr = prev.next
while curr and curr.next:
next = curr.next
curr.next = next.next
next.next = prev.next
prev.next = next
prev = prev.next.next
curr = curr.next
if curr == None: # edge cases, if there is one or two nodes
next = None
else:
next = curr.next
return dummy.next
25. Reverse Nodes in k-Group
方法同24题,当24理解了,可以做25,首先需要求出长度, 然后按照24的原理,成对,改为k 组。方法完全一样。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
prev = dummy = ListNode(0)
curr = head
dummy.next = head
length = 0
while head:
length += 1
head = head.next
for i in range(length // k):
for j in range(k - 1):
next = curr.next
curr.next = next.next
next.next = prev.next
prev.next = next
prev = curr
curr = prev.next
return dummy.next
26. Remove Duplicates from Sorted Array
method: 一次遍历,一个指针指向空位填充
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
index = 1
for i in range(1, len(nums)):
if nums[i-1] != nums[i]:
nums[index] = nums[i]
index += 1
return index
27. Remove Element
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i = len(nums) - 1
while i >= 0:
if nums[i] == val:
nums.remove(nums[i])
i -= 1
return len(nums)
28. Implement strStr()
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
if needle == '':
return 0
if needle in haystack:
return haystack.index(needle)
else:
return -1
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
n, h = len(needle), len(haystack)
i, j, nxt = 1, 0, [-1]+[0]*n
while i < n: # calculate next array
if j == -1 or needle[i] == needle[j]:
i += 1
j += 1
nxt[i] = j
else:
j = nxt[j]
i = j = 0
while i < h and j < n:
if j == -1 or haystack[i] == needle[j]:
i += 1
j += 1
else:
j = nxt[j]
return i-j if j == n else -1
29. Divide Two Integers
底层的除法按照位移运算可以加快速度,然后相减
if not dividend:
return 0
sign = 1 if (dividend > 0 and divisor < 0) or (dividend < 0 and divisor > 0) else 0
dividend = abs(dividend)
divisor = abs(divisor)
res = 0
while dividend >= divisor:
k = 0
while dividend >= divisor << (k + 1):
k += 1
dividend -= (divisor << k)
res += (1 << k)
MAX_INT = (1 << 31) - 1
return -res if sign else min(res,MAX_INT)
30. Substring with Concatenation of All Words
方法:sliding window
1 i, j 为window大小, i为输出下标。
2 Counter统计每个单词出现个数, m_length代表单词长度,n_word代表单词数量,也是跳出循环的条件。
3 内循环如果是单词数量超过规定数量,可以提前退出。时间复杂度O(n^2), 因为是两层循环。但能够解决如此复杂的问题。
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
ans = []
n_words, m_length = len(words), len(words[0])
words = collections.Counter(words)
for i in range(len(s) - n_words *m_length+1): # no need to iterate all
tmp = collections.Counter()
cnt = 0
for j in range(i,i+n_words *m_length, m_length): # at most n*m characters in the sliding window
w = s[j:j+m_length]
if w in words:
tmp[w]+=1
cnt+=1
if tmp[w]>words[w]: # ditch current sliding window
break
if cnt==n_words:
ans.append(i)
return ans