牛客刷题day6
文章目录
1.判断t1树中是否有与t2树拓扑结构
题目
给定彼此独立的两棵二叉树,判断 t1 树是否有与 t2 树拓扑结构完全相同的子树。
设 t1 树的边集为 E1,t2 树的边集为 E2,若 E2 等于 E1 ,则表示 t1 树和t2 树的拓扑结构完全相同。
解题思路
使用递归
时间复杂度:O ( M ∗ N )
当root1什么都没有的时候,在root1里面找不到任何节点直接返回false。
当root2提前终止了,此时还没有遇到不符合root1树的节点,直接返回true。
核心代码
class Solution:
def isContains(self , root1 , root2 ):
# write code here
if not root1 and not root2:
return True
if not root1 or not root2:
return False
return self.isEqual(root1,root2) or self.isContains(root1.left, root2) or self.isContains(root1.right, root2)
def isEqual(self,root1,root2):
if not root1 and not root2:
return True
if not root1 or not root2:
return False
return root1.val == root2.val and self.isEqual(root1.left, root2.left) and self.isEqual(root1.right, root2.right)
2.用两个栈实现队列
题目
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型
解题思路
队列先进先出,栈是先进后出
将进栈的元素反转不就是队列?刚好两个栈,将进栈的元素出栈 不就刚好实现栈的反转 即实现队列
核心代码
class Solution:
def __init__(self):
self.stack1 ,self.stack2 = [],[]
def push(self, node):
# write code here
self.stack1.append(node)
def pop(self):
# return xx
if self.stack2:
return self.stack2.pop()
if not self.stack1:
return None
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
3.最长回文字符串
题目
对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。
给定字符串A以及它的长度n,请返回最长回文子串的长度。
输入:“abc1234321ab”,12
输出:7
解题思路
1.(动态规划,O(n^2))
从第一个字符往后遍历,把每个字符都当作中心去向两边扩散,依次比较对称位置是否相等,当碰到左右边界停下。注意要分奇偶子串两种情况。
2. 马拉车算法,O(n))
在处理最长回文子串的时候,一般教科书上都会提一个线性的算法–Manacher大法,它可以将动态规划情况下的复杂度由n^2的复杂度降到线性。马拉车算法能将奇偶长度的子串归为一类,统一使用上面动态规划用的中心扩展法。它在原字符串中插入特殊字符,例如插入#后原字符串变成’#3#5#5#3#4#3#2#1#’。现在我们对新字符串使用中心扩展发即可,中心扩展法得到的半径就是子串的长度。但是在本题实际操练时,耗时上并没卵用。这里简单看下思路吧。说实话 这个算法我没看懂,不过为了给大家提供思路,还是贴出来
3.从头到尾遍历字符串,分奇偶字符串来判断,这个思想是牛客大佬的代码,我也是一步步打印才看明白,这个利用回文字符串特性,从头到尾扫描字符串,每增加一个新的字符,判断以这个字符结尾,大家可以用小例子试一下。且长度为maxLen+1或者maxLen+2的子串是否为回文,如果是,更新。这里长度为什么是maxLen+1或者maxLen+2,是要判断奇偶字符串。
核心代码
1.动态规划
class Solution:
def getLongestPalindrome(self, A, n):
def func(A, left, right):
while left >= 0 and right < n and A[left] == A[right]:
left -= 1
right += 1
return right - left - 1
res = 0
for i in range(n - 1):
res = max(res, func(A, i, i), func(A, i, i + 1))
return res
- 马拉车算法,O(n))
class Palindrome:
def getLongestPalindrome(self, A, n):
if n <= 1: return n
# 每个字符之间插入 #
ss = '$#' + '#'.join([x for x in A]) + '#`'
p = [1] * len(ss)
center = 0
mx = 0
max_str = ''
for i in range(1, len(p)-1):
if i < mx:
j = 2 * center - i # i 关于 center 的对称点
p[i] = min(p[j],mx-i)
# 尝试继续向两边扩展,更新 p[i]
while ss[i - p[i] ] == ss[i + p[i] ]: # 不必判断是否溢出,因为首位均有特殊字符,肯定会退出
p[i] += 1
# 更新中心
if i + p[i] - 1 > mx:
mx = i + p[i] - 1
center = i
# 更新最长串
if 2 * p[i]-1 > len(max_str):
max_str = ss[i - p[i]+1 : i + p[i]]
maxLen = len(max_str.replace('#', ''))
return maxLen
3.牛客大佬
class Solution:
def getLongestPalindrome(self, A, n):
# write code here
max_len = 0
for i in range(n):
# 一定先判断奇数回文串,在判断偶数回文串
oddNum = A[i-max_len-1:i+1]
evenNum = A[i-max_len:i+1]
if i-max_len-1>=0 and oddNum == oddNum[::-1]:
max_len+=2
elif i-max_len>=0 and evenNum == evenNum[::-1]:
max_len+=1
return max_len
4.数组中出现的数字超过一半
题目
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
解题思路
1.先将数组排序,记录每个数字重复次数,满足题目条件就直接输出
2.建立字典,记录每个数字重复次数
3.直接使用python列表统计函数count() python list count()用法
核心代码
#1.解题思路1
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
numbers.sort()
key = len(numbers)/2
count =0
value = 0
for i in numbers:
if value!=i:
value = i
count=1
else:
count+=1
if count>key:
return value
return 0
# 解题思路2:
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
dict1 = dict()
lenth = len(numbers)
for item in numbers:
if item not in dict1:
dict1[item] = 1
else:
dict1[item] += 1
for key, value in dict1.items():
if value > lenth // 2:
return key
return 0
# 解题思路三
```python
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
for i in numbers:
if numbers.count(i) > len(numbers)//2:
return i
return 0