leetcode
Posted 旧时星空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode相关的知识,希望对你有一定的参考价值。
leetcode(2)
根据二叉树创建字符串–简单
递归
class Solution:
def tree2str(self, root: Optional[TreeNode]) -> str:
if root is None:
return ""
if root.left is None and root.right is None:
return str(root.val)
if root.right is None:
return f"root.val(self.tree2str(root.left))"
return f"root.val(self.tree2str(root.left))(self.tree2str(root.right))"
迭代
我们也可以使用迭代的方法得到二叉树的前序遍历,并在迭代时加上额外的括号。
用一个栈来存储树中的一些节点,其中栈顶的元素为当前遍历到的节点,从栈底到栈顶的节点为从根到当前节点的唯一路径上的节点。和迭代得到前序遍历的方法略有不同,由于这里需要输出额外的括号,因此我们还需要用一个集合存储所有遍历过的节点,理由见下文。
首先我们把根节点入栈。对于当前栈顶的元素,如果它没有遍历过,那么就把它加入到集合中,并开始对以它为根的子树进行前序遍历。我们先在答案末尾添加一个 \\text`(’‘(’,表示一个节点的开始,然后判断该节点的子节点个数。
和方法一相同,这里会出现四种情况:
如果当前节点有两个孩子,那么我们先将右孩子入栈,再将左孩子入栈,从而保证前序遍历的顺序;
如果当前节点没有孩子,我们什么都不做;
如果当前节点只有左孩子,那么我们将左孩子入栈;
如果当前节点只有右孩子,那么需要在答案末尾添加一对 \\text()'‘()’ 表示空的左孩子,再将右孩子入栈。 注意这四种情况中,我们都不会将当前节点出栈,原因是我们一开始添加了 \\text
(’‘(’ 表示节点的开始,在以当前节点为根的子树中所有节点遍历完成之后,我们才会在答案末尾添加 \\text)'‘)’ 表示节点的结束。因此我们需要用上面提到的集合来存储遍历过的节点,如果当前栈顶的元素遍历过,那么就需要在答案末尾添加 \\text
)’‘)’ ,并将这个节点出栈。
class Solution:
def tree2str(self, root: Optional[TreeNode]) -> str:
ans = ""
st = [root]
vis = set()
while st:
node = st[-1]
if node in vis:
if node != root:
ans += ")"
st.pop()
else:
vis.add(node)
if node != root:
ans += "("
ans += str(node.val)
if node.left is None and node.right:
ans += "()"
if node.right:
st.append(node.right)
if node.left:
st.append(node.left)
return ans
具有所有最深节点的最小子树–中等
深度优先搜索
最直白的做法,先做一次深度优先搜索标记所有节点的深度来找到最深的节点,再做一次深度优先搜索用回溯法找最小子树。定义第二次深度优先搜索方法为 answer(node),每次递归有以下四种情况需要处理:
如果 node 没有左右子树,返回 node。
如果 node 左右子树的后代中都有最深节点,返回 node。
如果只有左子树或右子树中有且拥有所有的最深节点,返回这棵子树的根节点(即 node 的左/右孩子)。
否则,当前子树中不存在答案。
算法
先做一次深度优先搜索标记所有节点的深度,再做一次深度优先搜索找到最终答案。
class Solution(object):
def subtreeWithAllDeepest(self, root):
# Tag each node with it's depth.
depth = None: -1
def dfs(node, parent = None):
if node:
depth[node] = depth[parent] + 1
dfs(node.left, node)
dfs(node.right, node)
dfs(root)
max_depth = max(depth.itervalues())
def answer(node):
# Return the answer for the subtree at node.
if not node or depth.get(node, None) == max_depth:
return node
L, R = answer(node.left), answer(node.right)
return node if L and R else L or R
return answer(root)
作者:LeetCode
链接:https://leetcode-cn.com/problems/smallest-subtree-with-all-the-deepest-nodes/solution/ju-you-suo-you-zui-shen-jie-dian-de-zui-xiao-zi-sh/
下一个更大元素–中等
线性解法
这种方法中,我们同样将给定数字 nn 当做字符串数组 aa,首先我们观察到任意降序的序列,不会有更大的排列出现。
比方说,下面数列就没有下一排列:
[9, 5, 4, 3, 1]
我们需要从右往左找到第一对连续的数字 a[i]a[i] 和 a[i-1]a[i−1] 满足 a[i-1] < a[i]a[i−1]<a[i]。到当前位置位置位置,a[i-1]a[i−1] 右边的数字没办法产生一个更大的排列,因为右边的数字是降序的。所以我们需要重新排布 a[i-1]a[i−1] 到最右边的数字来得到下一个排列。
那么怎样排布能得到下一个更大的数字呢?我们想得到恰好大于当前数字的下一个排列,所以我们需要用恰好大于 a[i-1]a[i−1] 的数字去替换掉 a[i-1]a[i−1],比方说我们让这个数字为 a[j]a[j]。
我们将 a[i-1]a[i−1] 和 a[j]a[j] 交换,我们现在在下标为 i-1i−1 的地方得到了正确的数字,但当前的结果还不是一个正确的排列。我们需要用从 i-1i−1 开始到最右边数字剩下来的数字升序排列,来得到它们中的最小排列。
我们注意到在从右往左找到第一对 a[i-1] < a[i]a[i−1]<a[i] 的连续数字前, a[i-1]a[i−1] 右边的数字都是降序排列的,所以交换 a[i-1]a[i−1] 和 a[j]a[j] 不会改变下标从 ii 开始到最后的顺序。所以我们在交换了 a[i-1]a[i−1] 和 a[j]a[j] 以后,只需要反转下标从 ii 开始到最后的数字,就可以得到下一个字典序最小的排列。
class Solution
public:
int nextGreaterElement(int n)
string s = to_string(n);
int len = s.size();
int ptr = len - 2, revPtr = len - 1, ans = 0;
long long mul = 1, judge = 0;
//找ptr的位置
while(ptr >= 0)
if(s[ptr] - '0' < s[ptr + 1] - '0') break;
ptr--;
if(ptr < 0) return -1;
//确定revPtr的位置
while(revPtr > ptr) //这一步是在给它找初值,这个初值不是随便找的,必须也得是大于ptr元素
if(s[revPtr] - '0' > s[ptr] - '0') break;
revPtr--;
for(int i = len - 1; i > ptr; i--)
if(s[i]-'0' > s[ptr]-'0' && s[revPtr]-'0' > s[i]-'0') revPtr = i;
//调换两个的位置
char ch = s[ptr];
s[ptr] = s[revPtr];
s[revPtr] = ch;
//ptr右部分进行排序
sort(s.begin() + ptr + 1, s.end());
//string → int
for(int i = len - 1; i >= 0; i--)
judge += (s[i] - '0') * mul; //为了不溢出,先用一个long long型的数判断一下,有没有溢出
if(judge <= INT_MAX)
ans += (s[i] - '0') * mul;
mul *= 10;
else return -1;
return ans;
;
递增顺序查找树–中等
事实上,还可以遍历一次输入二叉搜索树,在遍历的过程中改变节点指向以满足题目的要求。
在中序遍历的时候,修改节点指向就可以实现。具体地,当我们遍历到一个节点时,把它的左孩子设为空,并将其本身作为上一个遍历到的节点的右孩子。这里需要有一些想象能力。递归遍历的过程中,由于递归函数的调用栈保存了节点的引用,因此上述操作可以实现。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def increasingBST(self, root):
dummy = TreeNode(-1)
self.prev = dummy
self.inOrder(root)
return dummy.right
def inOrder(self, root):
if not root:
return None
self.inOrder(root.left)
root.left = None
self.prev.right = root
self.prev = root
self.inOrder(root.right)
重新排列数组–简单
class Solution
public int[] shuffle(int[] nums, int n)
int len = nums.length;
int[] ans = new int[len];
int index = 0;
for(int i = 0;i < len - n;i++)
ans[index++] = nums[i];
ans[index++] = nums[i+n];
return ans;
以上是关于leetcode的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode Algorithm 572. 另一棵树的子树
[LeetCode] Count Univalue Subtrees 计数相同值子树的个数