寻找重复的子树
LeetCode652题,当二叉树中出现两个结构相同的节点时,将其加入结果中。
思路分析:
递归一个节点的子树,并且以一定的规则来得到一个key,需要保证这个规则使得这个key是唯一的,除非出现结构相同的节点,将key存入Map中,当出现的次数等于2时,将该节点插入结果集中。
List<TreeNode> result;
Map<Integer, Integer> counts;
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
result = new ArrayList();
counts = new HashMap();
dfs(root);
return result;
}
private int dfs(TreeNode node) {
if (node == null) return 3524335; //不一定要返回这个数
//规则可以自己定义,但必须保证唯一
int id = ((dfs(node.left) ^ 23) * 3423443 + (dfs(node.right) ^ 33)) * 3423443 + node.val;
int count = counts.getOrDefault(id, 0) + 1;
if (count == 2) {
result.add(node);
}
counts.put(id, count);
return id;
}
下一个更大元素
LeetCode503题,给定一个数组,要求返回每个元素第一个比它更大的数,可以循环搜索,如果不存在则为-1。
思路分析:
需要循环数组两遍,因为最后一个元素肯定是从头开始找的,并且不能保证现有的元素第一个比它更大的数就在其后面,所以需要搜索两次,第一次搜索需要保存,待查找的元素下标,每次循环时,拿当前的数和栈顶元素对比,当前的数一定是栈顶元素第一个比它更大的数。
int n = nums.length;
int [] res = new int[n];
//先将结果全部置为-1
Arrays.fill(res, -1);
//用于保存nums中的下标
Stack<Integer> stack = new Stack<>();
//循环两遍,找到最后几个元素下一个更大的元素
for (int i = 0; i < n*2; i++){
//取模防止下标越界
int num = nums[i % n];
//比较当前栈顶下标对应的元素,是否小于当前数
while(!stack.isEmpty() && num > nums[stack.peek()]){
//如果大于,则当前数一定是该下标元素最近的数
res[stack.pop()] = num;
}
//防止重复加
if(i < n) stack.add(i);
//优化:当第二次查找时,如果需要找的下标为空,则说明已经查找完毕了
if(i>=n && stack.isEmpty()){
return res;
}
}
return res;