文章目录
链表
2020/07/10 打卡
- 从尾到头打印链表:借助列表模拟堆栈
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
if not listNode:
return []
stack = []
p = listNode
while p:
stack.append(p.val)
p = p.next
return stack[::-1] # 列表反转,参考:https://www.runoob.com/note/51257
设置两个指针p和q,让q先走k-1步,然后两个指针一起走,等q走到了链表尾端,p所指的就是倒数第k个结点。
class Solution:
def FindKthToTail(self, head, k):
# write code here
if head == None or k<=0:
return None
p = head
q = p
while k-1:
if q.next != None:
q = q.next
k = k - 1
else:
return None
while q.next != None:
p = p.next
q = q.next
return p
输入一个链表,反转链表后,输出新链表的表头。
[1,2,3,4],q先置为Null,依次让1指向空,让2指向1,让3指向2…
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if pHead == None or pHead.next == None:
return pHead
q = None
while pHead.next != None:
p = pHead
pHead = pHead.next
p.next = q
q = p
pHead.next = q
return pHead
2020/07/11 打卡
- 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路: 思路很简单,比较两个链表的值,谁大指向谁
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
temp = ListNode(0) # 初始化一个链表
res = temp
while pHead1 and pHead2:
if pHead1.val < pHead2.val:
temp.next = pHead1
pHead1 = pHead1.next
temp = temp.next
else:
temp.next = pHead2
pHead2 = pHead2.next
temp = temp.next
if pHead1:
temp.next = pHead1
if pHead2:
temp.next = pHead2
return res.next
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if pHead == None:
return
# 第一步,完成链表节点的复制和单项指针的重指向
kk = pHead
while kk:
node = RandomListNode(kk.label) # 复制一个节点出来
# 这两句让新节点和链表做了左右相连
node.next = kk.next
kk.next = node
# 对链表的下一个节点做同样的操作
kk = node.next
# 第二步,复制random节点
kk = pHead
while kk:
if kk.random:
kk.next.random = kk.random.next
kk = kk.next.next
# 第三步,分离两个链表
kk = pHead
ee = pHead.next
nn = pHead.next
while kk:
# 让旧的next指针指向下一个旧节点
kk.next = kk.next.next
if nn.next:
# 让新的节点的next指针指向下一个新节点
nn.next = nn.next.next
nn = nn.next
kk = kk.next
return ee
啥是公共节点:
思路:
设两个链表长度差为k,先让长的那个走k步,再一起走,直到遇到相等节点。
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
p1 = pHead1
p2 = pHead2
i = 0
j = 0
while p1:
p1 = p1.next
i = i + 1
while p2:
p2 = p2.next
j = j + 1
if i > j:
while i-j:
pHead1 = pHead1.next
j = j + 1
else:
while j-i:
pHead2 = pHead2.next
i = i + 1
while pHead1 and pHead2:
if pHead1 == pHead2:
return pHead1
pHead1 = pHead1.next
pHead2 = pHead2.next
return None
2020/07/12 打卡
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
解题思路 :思路简单,指针乱七八糟,再也不想做链表题了 ==
为了防止第一个节点就是重复节点,需要初始化一个新的头节点;
设置三个指针,分别是当前指针cur,前一个指针pre,后一个指针nex,nex从前往后走,遇到重复的,就让cur指向nex,也就删掉了重复节点。
class Solution:
def deleteDuplication(self, pHead):
# write code here
if pHead == None or pHead.next == None:
return pHead
head = ListNode(0) # 为了防止第一个节点就是重复节点,重新弄个头节点
head.next = pHead
pre = head # 当前节点的前一个节点
cur = pHead # 当前节点
nex = None # 当前节点的后一个节点
while cur != None and cur.next != None:
nex = cur.next
if cur.val == nex.val:
while nex != None and nex.val == p.val:
nex = nex.next
pre.next = nex
cur = nex
else:
pre = cur
cur = cur.next
return head.next
累了╯︿╰。做做字符串的吧!
字符串
太简单啦哈哈哈哈哈哈哈o( ̄▽ ̄)ブ
class Solution:
# s 源字符串
def replaceSpace(self, s):
# write code here
t = ''
for i in s:
if i == ' ':
t = t + '%20'
else:
t = t + i
return t
- 表示数值的字符串:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
这个解法太流氓了哈哈哈哈哈哈今天的题目都好鬼畜??
不想写正则23333
class Solution:
# s字符串
def isNumeric(self, s):
# write code here
try:
s = float(s)
return True
except:
return False
2020/07/14 打卡
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
解题思路:
用的递归法,依次固定第一个元素,然后求剩余字符的排列。求剩余字符排列时跟原问题一样,递归求解。注意:set()的使用
class Solution:
def Permutation(self, ss):
# write code here
# 递归法,问题转换为先固定第一个字符,求剩余字符的排列;求剩余字符排列时跟原问题一样。
if len(ss) <= 1:
return ss
res = set()
for i in range(len(ss)):
for j in self.Permutation(ss[:i] + ss[i+1:]):# 固定元素i,除了i之外的全排列
res.add(ss[i] + j)
return sorted(res)
- 第一个只出现一次的字符位置
太简单了不说了
class Solution:
def FirstNotRepeatingChar(self,s):
# write code here
if len(s) == 0:
return -1
s = list(s)
for i in s:
if s.count(i) == 1:
return s.index(i)
return -1
- 左旋转字符串
太简单了不说了 就一行代码
class Solution:
def LeftRotateString(self, s, n):
# write code here
return s[n:]+s[:n]
2020/07/15 打卡
class Solution:
def StrToInt(self, s):
# write code here
if s is None:
return 0
lens = len(s)
if lens ==0:
return 0
res = 0
strat = 0
flag = 1
if s[0] == '+' or s[0] =='-':
strat = 1
if s[0] == '-':
flag = -1
for i in range(strat,lens):
if '0'<=s[i] and s[i] <= '9':
res = res*10+(ord(s[i])-ord('0'))
else:
return 0
if flag ==-1:
res = -res
return res
class Solution:
def ReverseSentence(self, s):
# write code here
if s.strip() != "":
return " ".join(s.split()[::-1])
else:
return s
- 正则表达式匹配
写不出。看的别人的答案。
# -*- coding:utf-8 -*-
class Solution:
# s, pattern都是字符串
def match(self, s, pattern):
# 如果s与pattern都为空,则True
if len(s) == 0 and len(pattern) == 0:
return True
# 如果s不为空,而pattern为空,则False
elif len(s) != 0 and len(pattern) == 0:
return False
# 如果s为空,而pattern不为空,则需要判断
elif len(s) == 0 and len(pattern) != 0:
# pattern中的第二个字符为*,则pattern后移两位继续比较
if len(pattern) > 1 and pattern[1] == '*':
return self.match(s, pattern[2:])
else:
return False
# s与pattern都不为空的情况
else:
# pattern的第二个字符为*的情况
if len(pattern) > 1 and pattern[1] == '*':
# s与pattern的第一个元素不同,则s不变,pattern后移两位,相当于pattern前两位当成空
if s[0] != pattern[0] and pattern[0] != '.':
return self.match(s, pattern[2:])
else:
# 如果s[0]与pattern[0]相同,且pattern[1]为*,这个时候有三种情况
# pattern后移2个,s不变;相当于把pattern前两位当成空,匹配后面的
# pattern后移2个,s后移1个;相当于pattern前两位与s[0]匹配
# pattern不变,s后移1个;相当于pattern前两位,与s中的多位进行匹配,因为*可以匹配多位
return self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:]) or self.match(s[1:], pattern)
# pattern第二个字符不为*的情况
else:
if s[0] == pattern[0] or pattern[0] == '.':
return self.match(s[1:], pattern[1:])
else:
return False
2020/07/16 打卡
二叉树
16. 重建二叉树
**要求:**输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:用的递归,很简单,不知道还有没有别的方法,以后再试。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if not pre:
return None
root = TreeNode(pre[0])
t = tin.index(pre[0])
root.left = self.reConstructBinaryTree(pre[1:t+1],tin[:t])
root.right = self.reConstructBinaryTree(pre[t+1:],tin[t+1:])
return root
17. 树的子结构
有点复杂不太会,看的答案 ==。
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
result = False
if pRoot1 and pRoot2:
if pRoot1.val==pRoot2.val:
result = self.DoesTree1HaveTree2(pRoot1,pRoot2)
if not result:
result = self.HasSubtree(pRoot1.left,pRoot2)
if not result:
result = self.HasSubtree(pRoot1.right,pRoot2)
return result
def DoesTree1HaveTree2(self,pRoot_A,pRoot_B):
if not pRoot_B:
return True
if not pRoot_A:
return False
if pRoot_A.val != pRoot_B.val:
return False
return self.DoesTree1HaveTree2(pRoot_A.left,pRoot_B.left) and self.DoesTree1HaveTree2(pRoot_A.right,pRoot_B.right)
题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。
解题思路:递归,很简单
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if not root:
return None
t = root.left
root.left = root.right
root.right = t
if root.left:
self.Mirror(root.left)
if root.right:
self.Mirror(root.right)
return root
2020/07/17 打卡
题目描述:
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
解题思路:
借助一个队列来实现,初始化让根节点进来,然后让根节点出队的同时,让根节点的左右节点进队,一直到队列为空结束。
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
if not root:
return []
queue = []
res = []
queue.append(root)
while len(queue) > 0:
t = queue.pop(0)
res.append(t.val)
if t.left:
queue.append(t.left)
if t.right:
queue.append(t.right)
return res
题目描述:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
解题思路:
什么是二叉搜索树?
也就是二叉排序树,根节点的值大于其左子树中任意一个节点的值,小于其右节点中任意一节点的值,这一规则适用于二叉查找树中的每一个节点。
递归实现:
class Solution:
def VerifySquenceOfBST(self,sequence):
# write code here
if not sequence:
return False
# 找到根节点
root = sequence[-1]
# 找到左子树
for i in range(len(sequence)):
if sequence[i]>root:
break
# 如果右子树有大于根节点的就false
for n in sequence[i:-1]:
if n < root:
print(111)
return False
# 如果有左子树,就递归检查左子树
left = right = True
if i-1 > 0:
left = self.VerifySquenceOfBST(sequence[:i-1])
if i < len(sequence)-2:
right = self.VerifySquenceOfBST(sequence[i:-1])
if left and right:
return True
else:
return False
- 二叉树中和为某一值的路径
输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
class Solution:
def FindPath(self, root, expectNumber):
result = []
if not root:
return result
#如果只有根节点或者找到叶子节点,就把其值返回
if not root.left and not root.right and root.val == expectNumber:
return [[root.val]]
else:
#如果不是叶子节点,分别对根节点的左子树、右子树进行递归,注意修改变量:
left = self.FindPath(root.left,expectNumber - root.val)
right = self.FindPath(root.right,expectNumber - root.val)
for item in left + right:
result.append([root.val]+item)
return result
2020/07/19 打卡
- 二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解题思路: 二叉搜索树:
变成双向有序链表的思路:本质上是中序遍历,同时需要改变指针指向。
class Solution:
def Convert(self, pRootOfTree):
# 中序遍历,遍历结果存在resStack里
if not pRootOfTree:
return None
p = pRootOfTree
stack = []
resStack = []
while p or stack:
if p:
stack.append(p)
p = p.left
else:
node = stack.pop()
resStack.append(node)
p = node.right
# 此时resStack已经是排好序的了,按照顺序连接成双链表
head = resStack[0] # 确定头节点
while resStack:
top = resStack.pop(0)
if resStack:
top.right = resStack[0]
resStack[0].left = top
return head
- 二叉树的深度
题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
解题思路:
递归,就很简单
class Solution:
def TreeDepth(self, pRoot):
# write code here
if not pRoot:
return 0
return 1 + max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right))
- 平衡二叉树
题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
由于不需要考虑其是不是排序二叉树,在这里只需满足:左子树与右子树的高度差不大于1即可。
从下往上遍历,如果子树是平衡二叉树,则返回子树的高度;如果发现子树不是平衡二叉树,则直接停止遍历,这样至多只对每个结点访问一次。
"""
从下往上遍历,如果子树是平衡二叉树,则返回子树的高度;如果发现子树不是平衡二叉树,则直接停止遍历,
这样至多只对每个结点访问一次。
"""
class Solution:
def IsBalanced_Solution(self, pRoot):
# write code here
if not pRoot:
return True
return self.getDeepth(pRoot)!= -1
def getDeepth(self, pRoot):
if not pRoot: return 0
left = self.getDeepth(pRoot.left)
if left == -1: return -1
right = self.getDeepth(pRoot.right)
if right == -1: return -1
if abs(left - right) > 1:
return -1
else:
return 1+max(left,right)
0721
25. 二叉树的下一个结点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
分两种情况:
- 有右子树的,则后一个节点就是右子树的最左边的节点,如C下一个是L;
- 无右子树的,又可以分成两种情况:a)无右子树,是父节点的左孩子,则下一个节点就是父节点;b)无右子树,是父节点的右孩子,则去找父节点的父节点,直到是上个父节点的左孩子为止;如果没找到,代表是最后一个,无下一个节点,如M。
class Solution:
def GetNext(self, pNode):
# write code here
if not pNode:
return None
if pNode.right:
p = pNode.right
while p.left:
p = p.left
return p
while pNode.next: #无右子树,则找第一个当前节点是父节点左孩子的节点
if (pNode.next.left == pNode):
return pNode.next
else:
pNode = pNode.next #沿着父节点向上遍历
return None
- 对称的二叉树
题目描述
请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路:递归的
class Solution:
def isSymmetrical(self, pRoot):
if not pRoot:
return True
return self.compare(pRoot.left, pRoot.right)
def compare(self, pRoot1, pRoot2):
if not pRoot1 and not pRoot2:
return True
if not pRoot1 or not pRoot2:
return False
if pRoot1.val == pRoot2.val:
if self.compare(pRoot1.left, pRoot2.right) and self.compare(pRoot1.right, pRoot2.left):
return True
return False
题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
解题思路: 这道题目是29题的变体。可以先做29题。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
# write code here
if not pRoot:
return []
queue = [pRoot]
res = []
row = 1
while queue:
row_list = []
next_queue = []
for i in queue:
row_list.append(i.val)
if i.left:
next_queue.append(i.left)
if i.right:
next_queue.append(i.right)
if row % 2:
res.append(row_list)
else:
res.append(row_list[::-1])
row = row + 1
queue = next_queue
return res
07/22
- 乱入一道题目:只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
思路:使用异或操作
a^0 = a:任意数和0做异或,结果为数字本身
a^a = 0:任意数和自身做异或,结果为数字本身
根据这个规律,将数组里的数字全部做异或,出现两次的元素异或结果为0,异或后的结果就是那个只出现了一次的元素。
class Solution:
def singleNumber(self, nums: List[int]) -> int:
res = 0
for i in nums:
res = res^i
return res
class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
# write code here
if not pRoot:
return []
queue = [pRoot]
res = []
while queue:
row_list = []
next_queue = []
for i in queue:
row_list.append(i.val)
if i.left:
next_queue.append(i.left)
if i.right:
next_queue.append(i.right)
res.append(row_list)
queue = next_queue
return res
- 二叉搜索树的第k个结点
中序遍历,遍历到第k个的时候停止。然而我实际上偷懒直接中序遍历后返回第k-1个值。
class Solution:
# 返回对应节点TreeNode
def KthNode(self, pRoot, k):
# write code here
# 中序遍历
if not pRoot:
return None
if k == 0:
return None
stack = []
res = []
curr = pRoot
while stack or curr:
if curr:
stack.append(curr)
curr = curr.left
else:
curr = stack.pop()
res.append(curr)
curr = curr.right
if k <= len(res):
return res[k-1]
else:
return None
2020/07/23
- 斐波那契数列
题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n<=39
解题思路:
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13,特别指出:第0项是0,第1项是第一个1。从第三项开始,每一项都等于前两项之和。
简单,搞一个递归,不用思考,我喜欢。
- 递归实现:
class Solution:
def Fibonacci(self, n):
# write code here
# f(n) = f(n-1) + f(n-2)
if n == 0:
return 0
if n == 1:
return 1
return self.Fibonacci(n-1) + self.Fibonacci(n-2)
尴尬的是,并没有通过,运行复杂度太高了。不怕,搞一个非递归的。
- 非递归实现
class Solution:
def Fibonacci(self, n):
# write code here
if n <= 0:
return 0
a = 0
b = 1
for i in range(n):
a, b = b, a+b
return a
- 跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
这个跟上个题目一模一样,跳到第n个台阶有两种跳法,一种是从n-2个台阶上跳上来,一种是从n-1个台阶上跳上来,因此递推公式:f(n) = f(n-1) + f(n-2)
class Solution:
def jumpFloor(self, number):
# write code here
if number <= 0:
return 0
if number == 1:
return 1
a = 1
b = 2
for i in range(number-1):
a, b = b, a+b
return a
- 变态跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
class Solution:
def jumpFloorII(self, number):
# write code here
if number <= 0:
return 0
if number == 1:
return 1
res = 1
for i in range(number-1):
res = res*2
return res
- 矩阵覆盖
题目描述
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?
比如n=3时,23的矩形块有3种覆盖方法:
解题思路:
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
if number == 0:
return 0
a = 1
b = 2
for i in range(number-1):
a, b = b, a+b
return a