剑指 offer day15-17
Posted six double seven@
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 offer day15-17相关的知识,希望对你有一定的参考价值。
257. 二叉树的所有路径
题目:
给你一个二叉树的根节点 root
,按任意顺序 ,返回所有从根节点到叶子节点的路径。
题解:
constructPaths
函数:
1.参数:当前节点,当前路径,以及最终返回的list集合paths
2.如果当前节点不为空,则将该节点添加到path中;
3.在不为空的基础上,判断当前节点是否为叶子节点,如果为叶子节点则代表这条path结束,将path添加至paths中;如果不是叶子节点,则继续遍历它的左右子树。
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();
constructPaths(root,"",res);
return res;
}
public void constructPaths(TreeNode root, String path, List<String> paths){
if (root!=null){
StringBuffer sb = new StringBuffer(path);
sb.append(Integer.toString(root.val));
if (root.left==null&&root.right==null){//为叶子节点
paths.add(sb.toString());
}else {
sb.append("->");
constructPaths(root.left,sb.toString(),paths);
constructPaths(root.right,sb.toString(),paths);
}
}
}
剑指 Offer 34. 二叉树中和为某一值的路径
题目:
给你二叉树的根节点root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
题解:
和上一题的思路一致。
public List<List<Integer>> pathSum(TreeNode root, int target) {
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
constructPaths(root,0,target,path,res);
return res;
}
public void constructPaths(TreeNode root, int sum,int target,List<Integer> path,List<List<Integer>> paths){
if (root!=null){
sum = sum + root.val;
List<Integer> list = new ArrayList<>(path);//用来获取截止到目前为止路径中的节点
list.add(root.val);
if (root.right==null&&root.left==null){
if (sum==target){
paths.add(list);
}
}else {
constructPaths(root.left,sum,target,list,paths);
constructPaths(root.right,sum,target,list,paths);
}
}
}
剑指 Offer 36. 二叉搜索树与双向链表
题目:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
题解:
1.对线索二叉树进行中序遍历,遍历结果为递增的,将结果存储在list集合中;
2.在主函数中,对list集合进行遍历,首先构成双向链表;
3.将双向链表的首尾连接形成双向循环链表。
public Node treeToDoublyList(Node root) {
if (root==null){
return null;
}
List<Integer> list = new ArrayList<>();
inOrderRecur(root,list);
Node head = new Node(list.get(0));
Node temp = head;
for (int i=1;i<list.size();i++){
Node node = new Node(list.get(i));
temp.right=node;
node.left=temp;
temp=temp.right;
}
temp.right=head;
head.left=temp;
return head;
}
public void inOrderRecur(Node root , List<Integer> list) {
if (root == null) {
return;
}
inOrderRecur(root.left,list);
list.add(root.val);
inOrderRecur(root.right,list);
}
剑指 Offer 54. 二叉搜索树的第k大节点
题目:
给定一棵二叉搜索树,请找出其中第k大的节点。
题解1:
按照上一题的思路,对线索二叉树进行中序遍历,将遍历结果存储在list集合中,返回list集合中第k大的值即可。
public int kthLargest(TreeNode root, int k) {
List<Integer> list = new ArrayList<>();
inOrderRecur(root,list);
return list.get(list.size()-k);
}
public void inOrderRecur(TreeNode root , List<Integer> list) {
if (root == null) {
return;
}
inOrderRecur(root.left,list);
list.add(root.val);
inOrderRecur(root.right,list);
}
题解2:
1.对线索二叉树进行遍历,遍历的顺序为先遍历右子树,再遍历根节点,再遍历左子树,遍历结果为递减序列;
2.使用全局变量sum来记录当前递归节点的个数,当sum==k时,表明此时根节点为第k大的值,结束递归返回值即可。
class Solution {
int k,res,sum=0;
public int kthLargest(TreeNode root, int k) {
this.k=k;
postOrderRecur(root);
return res;
}
public void postOrderRecur(TreeNode root) {
if (root == null) {
return ;
}
postOrderRecur(root.right);
sum++;//记录此时访问节点的数量
if (sum == k){
res = root.val;
return;
}
postOrderRecur(root.left);
}
}
剑指 Offer 45. 把数组排成最小的数
题目:
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
题解:
两个字符串a和b,如果a+b>b+a,则a应该在b的后面
Arrays.sort()
:[sort](…/…/java/util/Arrays.html#sort(T[], java.util.Comparator))(T[] a, Comparator<? super T> c)可以自定义一个比较器
public String minNumber(int[] nums) {
String[] strs = new String[nums.length];
for(int i = 0; i < nums.length; i++)
strs[i] = String.valueOf(nums[i]);
Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
StringBuilder res = new StringBuilder();
for(String s : strs)
res.append(s);
return res.toString();
}
剑指 Offer 61. 扑克牌中的顺子
题目:
从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
题解:
能够连成顺子的两个条件:
- 数组中无重复数字
- 最大值和最小值的差值最大为4
public boolean isStraight(int[] nums) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
Set<Integer> set = new HashSet<>();//确保没有重复的
for (int num:nums){
if(num == 0) continue; // 跳过大小王
min = Math.min(min,num);
max = Math.max(max,num);
if (set.contains(num)){
return false;
}
set.add(num);
}
return max-min<5;
}
剑指 Offer 40. 最小的k个数
题目:
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
题解:
直接sort
public int[] getLeastNumbers(int[] arr, int k) {
int[] res = new int[k];
Arrays.sort(arr);
for (int i=0;i<k;i++){
res[i]=arr[i];
}
return res;
}
剑指 Offer 41. 数据流中的中位数
题目:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
题解:
1.建立大顶堆和小顶堆:PriorityQueue<>()
默认建立小顶堆,PriorityQueue<>((x, y) -> (y - x))
建立大顶堆;
2.如果此时A和B两个堆的数量不相等,向B中add,反之向A中add;
3.在向B中add时,有可能此时的num并不属于较小的那一部分,因此需要先向A中add,然后将A的堆顶元素add至B中。
class MedianFinder {
Queue<Integer> A, B;
public MedianFinder() {
A = new PriorityQueue<>(); // 小顶堆,保存较大的一半
B = new PriorityQueue<>((x, y) -> (y - x)); // 实现大顶堆,保存较小的一半
}
public void addNum(int num) {
if(A.size() != B.size()) {
A.add(num);
B.add(A.poll());
} else {
B.add(num);
A.add(B.poll());
}
}
public double findMedian() {
return A.size() != B.size() ? A.peek() : (A.peek() + B.peek()) / 2.0;
}
}
emo了好久,我终于和自己和解了!
以上是关于剑指 offer day15-17的主要内容,如果未能解决你的问题,请参考以下文章