1.给你一个字符串类型的数组arr,譬如:
String[] arr = { “b\cst”, “d\”, “a\d\e”, “a\b\c” };
你把这些路径中蕴含的目录结构给画出来,子目录直接列在父目录下面,并比父目录
向右进两格,就像这样:
a
b
c
d
e
b
cst
d
同一级的需要按字母顺序排列,不能乱。
public class Problem01_GetFolderTree {
public static class Node {
public String name;
public TreeMap<String, Node> nextMap; //有序表:同一级的需要按字母顺序排列,不能乱
public Node(String name) {
this.name = name;
nextMap = new TreeMap<>();
}
}
public static void print(String[] folderPaths) {
if (folderPaths == null || folderPaths.length == 0) {
return;
}
Node head = generateFolderTree(folderPaths);//生成前缀树
printProcess(head, 0); //打印
}
public static Node generateFolderTree(String[] folderPaths) {
Node head = new Node("");
for (String foldPath : folderPaths) {
String[] paths = foldPath.split("\\\\");
Node cur = head;
for (int i = 0; i < paths.length; i++) {
if (!cur.nextMap.containsKey(paths[i])) {
cur.nextMap.put(paths[i], new Node(paths[i]));
}
cur = cur.nextMap.get(paths[i]);
}
}
return head;
}
public static void printProcess(Node head, int level) {//深度优先遍历
if (level != 0) {
System.out.println(get2nSpace(level) + head.name);
}
for (Node next : head.nextMap.values()) {
printProcess(next, level + 1);
}
}
public static String get2nSpace(int n) {//打印空格
String res = "";
for (int i = 1; i < n; i++) {
res += " ";
}
return res;
}
public static void main(String[] args) {
String[] arr = { "b\\cst", "d\\", "a\\d\\e", "a\\b\\c" };
print(arr);
}
2.剑指 Offer 36. 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。(二叉树的递归套路)
class Solution {
public static class Info{//定义信息的类
public Node start;
public Node end;
public Info(Node start,Node end){
this.start=start;
this.end=end;
}
}
public Node treeToDoublyList(Node root) {
if(root==null){
return null;
}
Info info = dfs(root);//递归的建立双向链表
info.end.right=info.start;//最终需要把链表的头和尾连到一起
info.start.left=info.end;
return info.start;
}
public static Info dfs(Node head){
if(head==null){
return new Info(null,null);
}
Info leftInfo=dfs(head.left);//左子树连成双向链表的头尾信息
Info rightInfo=dfs(head.right);//右子树连成双向链表的头尾信息
if(leftInfo.end!=null){
leftInfo.end.right=head;
}
if(rightInfo.start!=null){
rightInfo.start.left=head;
}
head.left=leftInfo.end;
head.right=rightInfo.start;
return new Info(leftInfo.start!=null ? leftInfo.start : head,rightInfo.end!=null ? rightInfo.end : head);
}
}
3.找到一棵二叉树中,最大的搜索二叉子树,返回最大搜索二叉子树的节点个数。
public static Node getMaxBST(Node head) {
return process(head).maxBSTHead;
}
public static class ReturnType {
public Node maxBSTHead;
public int maxBSTSize;
public int min;
public int max;
public ReturnType(Node maxBSTHead, int maxBSTSize, int min, int max) {
this.maxBSTHead = maxBSTHead;
this.maxBSTSize = maxBSTSize;
this.min = min;
this.max = max;
}
}
public static ReturnType process(Node X) {
// base case : 如果子树是空树
// 最小值为系统最大
// 最大值为系统最小
if (X == null) {
return new ReturnType(null, 0, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
// 默认直接得到左树全部信息
ReturnType lData = process(X.left);
// 默认直接得到右树全部信息
ReturnType rData = process(X.right);
// 以下过程为信息整合
// 同时以X为头的子树也做同样的要求,也需要返回如ReturnType描述的全部信息
// 以X为头的子树的最小值是:左树最小、右树最小、X的值,三者中最小的
int min = Math.min(X.value, Math.min(lData.min, rData.min)); //注意是min
// 以X为头的子树的最大值是:左树最大、右树最大、X的值,三者中最大的
int max = Math.max(X.value, Math.max(lData.max, rData.max));
// 如果只考虑可能性一和可能性二,以X为头的子树的最大搜索二叉树大小
int maxBSTSize = Math.max(lData.maxBSTSize, rData.maxBSTSize);
// 如果只考虑可能性一和可能性二,以X为头的子树的最大搜索二叉树头节点
Node maxBSTHead = lData.maxBSTSize >= rData.maxBSTSize ? lData.maxBSTHead
: rData.maxBSTHead;
// 利用收集的信息,可以判断是否存在可能性三
if (lData.maxBSTHead == X.left && rData.maxBSTHead == X.right
&& X.value > lData.max && X.value < rData.min) {
maxBSTSize = lData.maxBSTSize + rData.maxBSTSize + 1;
maxBSTHead = X;
}
// 信息全部搞定,返回
return new ReturnType(maxBSTHead, maxBSTSize, min, max);
}
4.已知一棵二叉树中没有重复节点,并且给定了这棵树的中序遍历数组和先序遍历
数组,返回后序遍历数组。
比如给定:
int[] pre = { 1, 2, 4, 5, 3, 6, 7 };
int[] in = { 4, 2, 5, 1, 6, 3, 7 };
返回:
{4,5,2,6,7,3,1}
public static int[] getPosArray1(int[] pre, int[] in) {
if(pre==null&&in==null){
return null;
}
int N=pre.length;
int [] pos=new int[N];
Map<Integer,Integer> map=new HashMap<>();//为了从in数组中找元素方便
for(int i=0;i<N;i++){
map.put(in[i],i);
}
set(pre,0,N-1,in,0,N-1,pos,0,N-1,map);//递归函数:pre数组从开始到结束的范围,in和pos类似
return pos;
}
//利用pre[prei....prej]与in[ini...inj]
//填好pos[posi...posj]
public static void set(int[] pre, int prei, int prej, int[] in, int ini, int inj, int[] pos, int posi, int posj, Map<Integer, Integer> map){
if(prej<prei){
return;
}
if(prei==prej){//表明只有一个元素了,直接赋值
pos[posi]=pre[prei];
return ;
}
pos[posj]=pre[prei];//pre的第一个元素是pos的最后一个元素
int find=map.get(pre[prei]);//找到元素在in中的位置
set(pre,prei+1,prei+find-ini,in,ini,find-1,pos,posi,posi+find-ini-1,map);
set(pre,prei+find-ini+1,prej ,in,find+1,inj ,pos,posi+find-ini,posj-1,map);
}
5.小Q正在给一条长度为n的道路设计路灯安置方案。
为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用’.‘表示, 不需要
照亮的障碍物格子用’X’表示。小Q现在要在道路上设置一些路灯, 对于安置在
pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。
小Q希望能安置尽量少的路灯照亮所有’.‘区域, 希望你能帮他计算一下最少需
要多少盏路灯。
输入描述:
输入的第一行包含一个正整数t(1 <= t <= 1000), 表示测试用例数
接下来每两行一个测试数据, 第一行一个正整数n(1 <= n <= 1000),表示道路
的长度。第二行一个字符串s表示道路的构造,只包含’.‘和’X’。
输出描述:
对于每个测试用例, 输出一个正整数表示最少需要多少盏路灯。
//s中只有'.'或者'X'两种字符
//路灯可以影响左中右三个位置
//至少需要多少灯可以把.都点亮
private static int minLight3(String test) {
char[] chars = test.toCharArray();
int light=0;
int index=0;
//当你来到i位置,一定保证之前的灯,彻底不会影响到i位置
while(index<chars.length){
if(chars[index]=='X'){
index++;
}else{//chars[index]=='.'
if(index+1==chars.length){
light++;
break;
}else{//如果下面有位置
if(chars[index+1]=='X'){
light++;
index=index+2;
}else{//下一个位置是. -> . . (放灯)
light++;
index=index+3;
}
}
}
}
return light;
}
6.(相似左神中级6-6)剑指offer42.连续子数组最大和
public int maxSubArray(int[] nums) {
if(nums==null||nums.length==0){
return 0;
}
int sum=Integer.MIN_VALUE;
int cur=0;
for(int i=0;i<nums.length;i++){
cur+=nums[i];
if(cur>sum){
sum=cur;
}
if(cur<0){
cur=0;
}
}
return sum;
}
7.给定一个整型矩阵,返回子矩阵的最大累计和.(化简为子数组最大值)
计算0-0,0-1,0-2,1-1,1-2,2-2的和,找出最大的
public static int maxSum1(int[][] matrix) {
if(matrix==null||matrix.length==0||matrix[0].length==0){
return 0;
}
int max=Integer.MIN_VALUE;
for(int i=0;i<matrix.length;i++){ //开始的行号i
int [] s=new int [matrix[0].length]; //当算0-2时,s为了把之前的都加起来。
for(int j=i;j<matrix.length;j++){ //结束的行号j,i-j是讨论的范围
int cur=0;
for(int k=0;k<s.length;k++){
s[k]+=matrix[j][k];
cur+=s[k];
if(cur>max){
max=cur;
}
if(cur<0){
cur=0;
}
}
}
}
return max;
}