给你一棵二叉树的根节点 root ,请你构造一个下标从 0 开始、大小为 m x n 的字符串矩阵 res ,用以表示树的 格式化布局 。构造此格式化布局矩阵需要遵循以下规则:
返回构造得到的矩阵 res 。
首先要确定树的高度h, 根据树的高度初始化一个 ( h + 1 ) × 2 h e i g h t + 1 (h+1) \times 2^{height+1} (h+1)×2height+1 - 1$的矩阵, 先把每个位置的初始值都设为"",然后利用dfs对树从根节点开始遍历,若左子树不为空则在对应位置上填入其值,同样右子树也是.
class Solution {
int h , m, n;
List<List<String>> ans = new ArrayList<>();
public List<List<String>> printTree(TreeNode root) {
if (root==null) return null;
getHeight(root, 0);
m = h+1;
n= (int) (Math.pow(2, h+1))-1;
for (int i = 0; i < m; i++) {
List<String> list = new ArrayList<>();
for (int j = 0; j < n; j++) {
list.add("");
}
ans.add(list);
}
dfs(root, 0, (n-1)/2);
return ans;
}
public void getHeight(TreeNode root, int depth){
if (root == null) return;
h = Math.max(depth, h);
getHeight(root.left, depth+1);
getHeight(root.right, depth+1);
}
public void dfs(TreeNode root, int r, int c){
if (root==null) return;
ans.get(r).set(c, String.valueOf(root.val));
int t = (int) Math.pow(2, h-r-1);
dfs(root.left, r+1, c-t);
dfs(root.right, r+1, c+t);
}
}
给定一个只包含整数的有序数组 nums ,每个元素都会出现两次,唯有一个数只会出现一次,请找出这个唯一的数字。
你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。
因为要求 O(log n) 时间复杂度和 O(1) 空间复杂度故想到使用二分查找.可以根据二分点mid的奇偶性进行分情况讨论:
class Solution {
public int singleNonDuplicate(int[] nums) {
int n = nums.length;
int res = 0;
int l = 0, r = nums.length - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (mid<n-1 && nums[mid] == nums[mid+1]){
if (mid%2==0) l=mid+2;
else r=mid-1;
}
else if (mid>0 && nums[mid] == nums[mid-1]){
if (mid%2==0) r=mid-2;
else l=mid+1;
}
else {
res = nums[mid];
break;
}
}
return res;
}
}
符合下列属性的数组 arr 称为 山峰数组(山脉数组) :
给定由整数组成的山峰数组 arr ,返回任何满足 arr[0] < arr[1] < … arr[i - 1] < arr[i] > arr[i + 1] > … > arr[arr.length - 1] 的下标 i ,即山峰顶部。很容易想到时间复杂度 O(n) 的解决方案,你可以设计一个 O(log(n)) 的解决方案吗?
由于需要复杂度O(log(n)) 的解决方案,故采用二分查找.利用题目发现如下性质:由于 arr 数值各不相同,因此峰顶元素左侧必然满足严格单调递增,峰顶元素右侧必然不满足。因此 以峰顶元素为分割点的 arr 数组,根据与 前一元素/后一元素 的大小关系,具有二段性:
class Solution {
public int peakIndexInMountainArray(int[] arr) {
int l = 0, r = arr.length-1;
int ans = 0;
while (l<=r){
int mid = (l+r)/2;
if (arr[mid]>arr[mid+1]){
ans = mid;
r = mid-1;
}else l = mid+1;
}
return ans;
}
}
给定一个非负整数 x ,计算并返回 x 的平方根,即实现 int sqrt(int x) 函数。正数的平方根有两个,只输出其中的正数平方根。
如果平方根不是整数,输出只保留整数的部分,小数部分将被舍去。
使用二分查找,如果当前mid*mid<=x,则l=mid+1; 反之r=mid-1.
class Solution {
public int mySqrt(int x) {
if (x==0) return 0;
int l = 0, r = x, ans=-1;
while (l <= r){
int mid = l + (r-l)/2;
if ((long) mid*mid <= x){
ans = mid;
l = mid+1;
}else r = mid - 1;
}
return ans;
}
}
给你一棵二叉树的根节点 root ,返回树的 最大宽度 。
树的 最大宽度 是所有层中最大的 宽度 。
每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。
输入:root = [1,3,2,5,3,null,9]
输出:4
解释:最大宽度出现在树的第 3 层,宽度为 4 (5,3,null,9) 。
使用DFS遍历二叉树, 同时用一个哈希表来记录当前遍历节点的
在 DFS过程中使用两个哈希表分别记录每层深度中的最小节点编号和最大节点编号,两者距离即是当前层的宽度,最终所有层数中的最大宽度即是答案。而实现上利用先 DFS 左节点,再 DFS 右节点的性质可知,每层的最左节点必然是最先被遍历到,因此我们只需要记录当前层最先被遍历到点编号(即当前层最小节点编号),并在 DFS 过程中计算宽度,更新答案即可。
class Solution {
Map<Integer, Integer> map = new HashMap<>();
int ans;
public int widthOfBinaryTree(TreeNode root) {
dfs(root, 1, 0);
return ans;
}
void dfs(TreeNode root, int u, int depth) {
if (root == null) return ;
if (!map.containsKey(depth)) map.put(depth, u);
ans = Math.max(ans, u - map.get(depth) + 1);
dfs(root.left, u << 1, depth + 1);
dfs(root.right, u << 1 | 1, depth + 1);
}
}