方法一:得到一个排序后的数组,然后遍历原数组,查找当前数字在排序后数组中的位置,即为当前数字的逆序数,累加后在原数组中删掉该数,接着往后处理,会超时
class Solution:
def reversePairs(self, nums: List[int]) -> int:
count = 0
sorted_nums = sorted(nums)
for i in nums:
count = count+sorted_nums.index(i)
sorted_nums.remove(i)
return count
方法二:剑指方法,参考归并排序,先把所有的数据分成每两个一个小组,统计逆序数后排序,然后把相邻的每两个含有两个数字的小组组成一个有四个数字的组,在组合的时侯统计逆序对并排序
class Solution:
def mergeSort(self, nums, tmp, l, r):
if l >= r:
return 0
mid = (l + r) // 2
inv_count = self.mergeSort(nums, tmp, l, mid) + self.mergeSort(nums, tmp, mid + 1, r)
i, j, pos = l, mid + 1, l
while i <= mid and j <= r:
if nums[i] <= nums[j]:
tmp[pos] = nums[i]
i += 1
inv_count += (j - (mid + 1))
else:
tmp[pos] = nums[j]
j += 1
pos += 1
for k in range(i, mid + 1):
tmp[pos] = nums[k]
inv_count += (j - (mid + 1))
pos += 1
for k in range(j, r + 1):
tmp[pos] = nums[k]
pos += 1
nums[l:r+1] = tmp[l:r+1]
return inv_count
def reversePairs(self, nums: List[int]) -> int:
n = len(nums)
tmp = [0] * n
return self.mergeSort(nums, tmp, 0, n - 1)
方法一:先遍历第一个链表,每个节点都在链表二中查找有没有,时间复杂度m*n
方法二:因为这种链表呈现的是一个y字型,所以可以从后往前比较,第一个出现不同的节点就是分叉的地方,所以可以用两个栈分别存下两条路径的节点,然后从后往前比较,时间复杂度m+n,空间复杂度m+n
方法三:先挨个遍历链表记录两个的长度,然后让长的先走差值步,短的再开始走,碰到的第一个相同的节点即为第一个公共节点
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
len_A = 0
len_B = 0
temp_A = headA
temp_B = headB
while headA:
len_A += 1
headA = headA.next
while headB:
len_B += 1
headB = headB.next
if len_A > len_B:
headA = temp_A
headB = temp_B
for i in range(len_A - len_B):
headA = headA.next
while headA != headB and headA:
headA = headA.next
headB = headB.next
else:
headA = temp_A
headB = temp_B
for i in range(len_B - len_A):
headB = headB.next
while headA != headB and headA:
headA = headA.next
headB = headB.next
if not headA:
return None
else:
return headA
方法:二分查找分别找到第一个k记下索引,再找到第二个k记下索引,求差,时间复杂度nlogn
class Solution:
def search(self, nums: [int], target: int) -> int:
# 搜索右边界 right
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] <= target: i = m + 1
else: j = m - 1
right = i
# 若数组中无 target ,则提前返回
if j >= 0 and nums[j] != target: return 0
# 搜索左边界 left
i = 0
while i <= j:
m = (i + j) // 2
if nums[m] < target: i = m + 1
else: j = m - 1
left = j
return right - left - 1
方法:二分查找,如果中间数的索引和数值相等则检查右边,反之检查左边
方法:二分查找,如果中间数的索引小于数值,则检查左边,反之检查右边
方法:二叉搜索树中序遍历得到的就是一个排序的结果
class Solution:
# 返回对应节点TreeNode
def KthNode(self, pRoot, k):
# write code here
global list
list = []
self.inorder(pRoot)
if k <= 0 or k > len(list): # 越界
return None
return list[k-1]
def inorder(self,pRoot):
if pRoot == None:
return None
self.inorder(pRoot.left)
list.append(pRoot)
self.inorder(pRoot.right)
方法一:递归,二叉树的深度等于max(左子树深度,右子树深度)+1
def depth(root):
if root is None:
return 0
ld = depth(root.left)
rd = depth(root.right)
return max(ld,rd)+1
方法二:迭代,层序遍历,每遍历完一层深度累加1
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root: return 0
queue, res = [root], 0
while queue:
tmp = []
for node in queue:
if node.left: tmp.append(node.left)
if node.right: tmp.append(node.right)
queue = tmp
res += 1
return res
方法:后序遍历,在遍历的时候记录每个节点的深度
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def recur(root):
if not root: return 0
left = recur(root.left)
if left == -1: return -1
right = recur(root.right)
if right == -1: return -1
return max(left, right) + 1 if abs(left - right) <= 1 else -1
return recur(root) != -1
方法:利用的思想是,一个数字抑或自己结果为0,所以先将所有的数字抑或一次,得到的结果不为0,找到为1的位,用该位将原始数据分成两类,所以两个不相同的数字也被分到了两个组里,然后对每组进行刚才的操作,最后的结果就是两个要求的只出现一次的数
class Solution(object):
def singleNumbers(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
temp = 0
for i in nums:
temp = temp^i
flag = 1
#从右往左找到第一个出现1的位
while(1):
bitone = temp & flag
if bitone!=0:
break
flag = flag<<1
num1 =[]
num2 = []
for i in nums:
if bitone&i==bitone:
num1.append(i)
else:
num2.append(i)
temp1 = 0
for i in num1:
temp1 = temp1^i
temp2 = 0
for i in num2:
temp2 = temp2^i
return([temp1,temp2])
方法1:把所有数字的二进制表示的每一位加起来,最后的结果如果那一位可以被3整除,说明只出现一次的那个数的那一位是0,反之是1,需要一个长度为32位的辅助空间,时间复杂度n
class Solution:
def singleNumber(self, nums: List[int]) -> int:
res = 0
for i in range(32):
cnt = 0
idx = 1<
方法2:(set(num)求和乘以3减去num和)//2
方法3:将每个数的次数存到哈希表中,结束后查哈希表中只出现一次的数字
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
dic = {}
for i in nums:
if i in dic:
dic[i] += 1
else:
dic[i] = 1
for i,j in dic.items():
if j == 1:
return i
方法:设置两个指针分别位于数组的头和尾,然后根据和的大小来往前或者往后移动
#如果有多对,输出积最小的
class Solution:
def FindNumbersWithSum(self, array, tsum):
# write code here
i = 0
j = len(array)-1
result = []
while itsum):
j = j-1
elif (array[i]+array[j]
方法:初始化一个[1,2]的list,如果该序列的数小于s,则后面增加一个3,如果大,则前面减少一个1,while的终止条件是,small
class Solution:
def FindContinuousSequence(self, tsum):
# write code here
result = []
i=1
j=2
sumnum =i+j
while i
方法一:最直观的方法,从后往前挨个单词找,放到新的list中,直到把每次单词都找到
class Solution:
def reverseWords(self, s: str) -> str:
s = s.strip() # 删除首尾空格
i = j = len(s) - 1
res = []
while i >= 0:
while i >= 0 and s[i] != ' ':
i -= 1 # 搜索首个空格
res.append(s[i + 1: j + 1]) # 添加单词
while s[i] == ' ':
i -= 1 # 跳过单词间空格
j = i # j 指向下个单词的尾字符
return ' '.join(res) # 拼接并返回
方法二:翻转两次,先整体翻转,再单词内部翻转,需要单独写一个函数用于翻转
方法三:用split函数分割到list中,然后reverse()
方法一:分成两部分ab和cdefg,先分别翻转这两部分ba和gfedc,再翻转整个字符串
方法二:list切片s[n:]+s[:n]
方法一:简单直接每次max(k)个数的最大值,依次保存,时间复杂度kn
class Solution:
def maxInWindows(self, num, size):
# write code here
if size==0 or size>len(num):
return []
temp = num[0:size]
tempmax = max(temp)
result = [tempmax]
for i in range(size,len(num)):
if tempmax==num[i-size] or num[i]>tempmax:
tempmax = max(num[i-size+1:i+1])
result.append(tempmax)
return result
方法二:在一个新list里,每次保存当前的最大值的索引,当往后移动一位时,先核对下标,若最大值下表在比新数小k的范围内,比较新数和当前的最大值,若小于最大值,则将新数的索引append到list后,若大于最大值,则直接替换掉原list。太难了。。。
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
deque = [];result = [] # deque也可以用collection里的双端队列实现
for i in range(0, len(nums)):
while deque and nums[i]>nums[deque[-1]]: # 只存有可能成为最大值的数字的index进deque
deque.pop()
deque.append(i)
while i-deque[0]>k-1: # 如果相距超过窗口k长度则弃掉
deque.pop(0)
if i >= k-1: #前两个不做处理
result.append(nums[deque[0]]) # 这过程中始终保持deque[0]为最大值的index
return result
方法:设置一个辅助队列queuemax用来存放当前状态下的最大值,具体操作为,每当push时,从后开始比较queuemax的值和当前要插入的值,将比它小的都删除,然后压入当前值,pop时,直接返回queuemax中的值,当pop的值和queuemax中最前面的值相等的时候,将queuemax最前面的值也pop出。
class MaxQueue(object):
def __init__(self):
self.que = []
self.sort_que = []
def max_value(self):
return self.sort_que[0] if self.sort_que else -1
def push_back(self, value):
self.que.append(value)
while self.sort_que and self.sort_que[-1] < value:
self.sort_que.pop()
self.sort_que.append(value)
def pop_front(self):
if not self.que: return -1
res = self.que.pop(0)
if res == self.sort_que[0]:
self.sort_que.pop(0)
return res
方法1:迭代,找规律,掷n次可能出现的点数和的所有可能性为6*n,用cnts数组记录对应点数出现的次数,初始值为[0,1,1,1,1,1,1,0,0,0,0.....],每掷一次从后往前更新。
class Solution:
def twoSum(self, n: int) -> List[float]:
if n == 0:
return []
# 初始化 1 - 6 是 1次,7 - n 是 0 次。
# 编号从1开始,这样方便写代码。 为了从1开始,我们只需要在数组前面随便push一个元素即可,比如本例的0
cnts = [0] + [1] * 6 + [0] * (6 * n - 6)
# 模拟投掷 n - 1 次
for _ in range(n - 1):
# 从后向前更新
for i in range(6 * n, 0, -1):
cnts[i] = sum(cnts[max(i - 6, 0): i])
return [i/6**n for i in cunts[1:]]
方法二:递归
class Solution:
def twoSum(self, n: int) -> List[float]:
def diceCnt(n):
if n == 1:
return [0] + [1] * 6
cnts = diceCnt(n - 1) + [0] * 6
for i in range(6 * n, 0, -1):
cnts[i] = sum(cnts[max(i - 6, 0): i])
return cnts
return [i/6**n for i in diceCnt(n)[1:]]