public static int treeDepth(BinaryTreeNode root) {
if (root == null) {
return 0;
}
int left = treeDepth(root.left);
int right = treeDepth(root.right);
return left > right ? (left + 1) : (right + 1);
}
【3】根据中序和后序遍历结果重建二叉树
【3】根据中序和前序遍历结果重建二叉树
public static BinaryTreeNode construct(int[] preorder, int ps, int pe,
int[] inorder, int is, int ie) {
// 开始位置大于结束位置说明已经没有需要处理的元素了
if (ps > pe) {
return null;
}
// 取前序遍历的第一个数字,就是当前的根结点
int value = preorder[ps];
int index = is;
// 在中序遍历的数组中找根结点的位置
while (index <= ie && inorder[index] != value) {
index++;
}
// 如果在整个中序遍历的数组中没有找到,说明输入的参数是不合法的,抛出异常
if (index > ie) {
throw new RuntimeException("Invalid input");
}
// 创建当前的根结点,并且为结点赋值
BinaryTreeNode node = new BinaryTreeNode();
node.value = value;
// 递归构建当前根结点的左子树,左子树的元素个数:index-is+1个
// 左子树对应的前序遍历的位置在[ps+1, ps+index-is]
// 左子树对应的中序遍历的位置在[is, index-1]
node.left = construct(preorder, ps + 1, ps + index - is, inorder, is,
index - 1); // 递归构建当前根结点的右子树,右子树的元素个数:ie-index个
// 右子树对应的前序遍历的位置在[ps+index-is+1, pe]
// 右子树对应的中序遍历的位置在[index+1, ie]
node.right = construct(preorder, ps + index - is + 1, pe, inorder,
index + 1, ie); // 返回创建的根结点
return node;
}
public static boolean verifySequenceOfBST(int[] sequence, int start, int end) {
// 如果对应要处理的数据只有一个或者已经没有数据要处理(start>end)就返回true
if (start >= end) {
return true;
}
// 从左向右找第一个不大于根结点(sequence[end])的元素的位置
int index = start;
while (index < end - 1 && sequence[index] < sequence[end]) {
index++;
}
// 执行到此处[end, index-1]的元素都是小于根结点的(sequence[end]) // [end,
// index-1]可以看作是根结点的左子树
// right用于记录第一个不小于根结点的元素的位置
int right = index;
// 接下来要保证[index, end-1]的所有元素都是大于根根点的【A】
// 因为[index, end-1]只有成为根结点的右子树
// 从第一个不小于根结点的元素开始,找第一个不大于根结点的元素
while (index < end - 1 && sequence[index] > sequence[end]) {
index++;
}
// 如果【A】条件满足,那么一定有index=end-1,
// 如果不满足那说明根结点的右子树[index, end-1]中有小于等于根结点的元素, // 不符合二叉搜索树的定义,返回false
if (index != end - 1) {
return false;
}
// 执行到此处说明直到目前为止,还是合法的 // [start, index-1]为根结点左子树的位置
// [index, end-1]为根结点右子树的位置
index = right;
return verifySequenceOfBST(sequence, start, index - 1)
&& verifySequenceOfBST(sequence, index, end - 1);
}
【3】二叉树中和为某个值的路径
public static void findPath(BinaryTreeNode root, int curSum,
int expectedSum, List result) {
// 如果结点不为空就进行处理
if (root != null) {
// 加上当前结点的值
curSum += root.value;
// 将当前结点入队
result.add(root.value);
// 如果当前结点的值小于期望的和
if (curSum < expectedSum) {
// 递归处理左子树
findPath(root.left, curSum, expectedSum, result);
// 递归处理右子树
findPath(root.right, curSum, expectedSum, result);
}
// 如果当前和与期望的和相等
else if (curSum == expectedSum) {
// 当前结点是叶结点,则输出结果
if (root.left == null && root.right == null) {
System.out.println(result);
}
}
// 移除当前结点,回溯吧
result.remove(result.size() - 1);
}
}
【3*】二叉树中某个节点的下一个节点 (强烈推荐准备一下,剑指 offer 第 58 题)
递归、动态规划
股票买入卖出的最佳时间
public int maxProfit(int num[]){
int max=-1;
int ans=-1;
for(inti=len-1;i>=0;i--)
if(num[i]>max)
max=num[i];
if(max-num[i]>ans)
ans=max-num[i];
return ans;
}
【2】递归方法求数组的最大值
int max(int arr[], int len) {
if (1 == len){ // 只有一个元素
return arr[0];
}
int a = arr[0]; // 第一个元素
int b = max(arr + 1, len - 1); // 第二个元素起的最大值
return a > b ? a : b;
}
【2】背包问题
【3】连续子数组的最大和
【4】实现简单的正则表达式匹配
字符串
【2】给一串字符串比如abbbcccd,输出a1b3c3d1,O(n)
public static void main(String[] args) {
String str= "abbbcccd";
int[] count= new int[256];
for (int i = 0 ;i0){
System.out.printf("%c%d",i,count[i]);
}
}
}
【2】例如输入字符串”I am a student. ”,则输出”student. a am I”
public static void reverse(char[] data, int start, int end) {
if (data == null || data.length < 1 || start < 0 || end > data.length
|| start > end) {
return;
}
while (start < end) {
char tmp = data[start];
data[start] = data[end];
data[end] = tmp;
start++;
end--;
}
}
public static char[] reverseSentence(char[] data) {
if (data == null || data.length < 1) {
return data;
}
reverse(data, 0, data.length - 1);// 首先全局逆转
int start = 0;
int end = 0;
while (start < data.length) {
if (data[start] == ' ') { // 排除开头空格
start++;
end++;
} else if (end == data.length || data[end] == ' ') {// 单词结束边界
reverse(data, start, end - 1);
end++;
start = end;
} else {
end++;
}
}
return data;
}
【2】比如输入字符串”abcefg”和数字 2,该函数将返回左旋转 2 位得到的结”cdefab”
public static void reverse(char[] data, int start, int end) {
if (data == null || data.length < 1 || start < 0 || end > data.length
|| start > end) {
return;
}
while (start < end) {
char tmp = data[start];
data[start] = data[end];
data[end] = tmp;
start++;
end--;
}
}
public static char[] leftRotateString(char[] data, int n) {
if (data == null || n < 0 || n > data.length) {
return data;
}
reverse(data, 0, data.length - 1);
reverse(data, 0, data.length - n - 1);
reverse(data, data.length - n, data.length - 1);
return data;
}
【2】java判断是否是回文字符
public static boolean isPalidrome(Stringstr){
char[] ch=str.toCharArray();
int len=ch.length;
for(inti=0,intj=len-1;i<=j;){
if(ch[i++]==ch[j--]){
}else{
return false;
}
}
return ture;
}
【3】最长回文子串
【3】最长无重复子串
【1*】字符串转数字
【4】KMP 算法
【2】字符串全排列
public static void permutation(char[] chars, int begin) { // 如果是最后一个元素了,就输出排列结果
if (chars.length - 1 == begin) {
System.out.print(new String(chars) + " ");
} else {
char tmp;
// 对当前还未处理的字符串进行处理,每个字符都可以作为当前处理位置的元素
for (int i = begin; i < chars.length; i++) {
// 下面是交换元素的位置
tmp = chars[begin];
chars[begin] = chars[i];
chars[i] = tmp;
// 处理下一个位置
permutation(chars, begin + 1);
// 恢复
tmp = chars[begin];
chars[begin] = chars[i];
chars[i] = tmp;
}
}
}```
【2*】翻转字符串
排序
归并排序、拓展:求数组中的逆序对个数
快速排序 重点:partion 函数的实现
堆排序
数组元素值域已知时,考虑 基数排序 和 桶排序
大数据
1.【3】海量N个数中求前M大个数(选择第M大数)
数组、矩阵
回形矩阵
public static void spiralOrderPrint(int[][] matrix) {
int tR = 0;
int tC = 0;
int dR = matrix.length - 1;
int dC = matrix[0].length - 1;
while (tR <= dR && tC <= dC) {
printEdge(matrix, tR++, tC++, dR--, dC--);
}
}
public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
if (tR == dR) { // 子矩阵只有一行时
for (int i = tC; i <= dC; i++) {
System.out.print(m[tR][i] + " ");
}
} else if (tC == dC) { // 子矩阵只有一列时
for (int i = tR; i <= dR; i++) {
System.out.print(m[i][tC] + " ");
}
} else { // 一般情况
int curC = tC;
int curR = tR;
while (curC != dC) {
System.out.print(m[tR][curC] + " ");
curC++;
}
while (curR != dR) {
System.out.print(m[curR][dC] + " ");
curR++;
}
while (curC != tC) {
System.out.print(m[dR][curC] + " ");
curC--;
}
while (curR != tR) {
System.out.print(m[curR][tC] + " ");
curR--;
}
}
}```
蛇形矩阵
【2】在排序数组中查找和为给定值的两个数字(思路)
找到数组的第一个数字和最后一个数字。
当两个数字的和大于输入的数字时,把较大的数字往前移动;
当两个数字的和小于数字时,把较小的数字往后移动;
当相等时,输出等式。这样扫描的顺序是从数组的两端向数组的中间扫描。
位运算
【2】给一个十进制数字,求它的二进制表示中,有多少个 1 (n &= n - 1)
【3】给一个数组,所有数字都出现了偶数次,只有一个出现了一次,找出这个数
【4】给一个数组,所有数字都出现了三次,只有一个出现了一次,找出这个数
【3】给一个数组,所有数组都出现了偶数次,只有两个数字出现了一次,找出这两个数
JAVA相关题
【2】生产者/消费者(wait() / notify()方法)
public class Storage {
// 仓库最大存储量
private final int MAX_SIZE = 100;
// 仓库存储的载体
private LinkedList
【3】生产者/消费者(await() / signal()方法)
public class Storage {
// 仓库最大存储量
private final int MAX_SIZE = 100;
// 仓库存储的载体
private LinkedList list = new LinkedList();
// 锁
private final Lock lock = new ReentrantLock();
// 仓库满的条件变量
private final Condition full = lock.newCondition();
// 仓库空的条件变量
private final Condition empty = lock.newCondition();
// 生产num个产品
public void produce(int num) {
// 获得锁
lock.lock();
// 如果仓库剩余容量不足
while (list.size() + num > MAX_SIZE) {
try {
full.await(); // 由于条件不满足,生产阻塞
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生产条件满足情况下,生产num个产品
for (int i = 1; i <= num; ++i) {
list.add(new Object());
}
// 唤醒其他所有线程
full.signalAll();
empty.signalAll();
// 释放锁
lock.unlock();
}
// 消费num个产品
public void consume(int num) {
// 获得锁
lock.lock();
// 如果仓库存储量不足
while (list.size() < num) {
try {
empty.await(); // 由于条件不满足,消费阻塞
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
// 消费条件满足情况下,消费num个产品
for (int i = 1; i <= num; ++i) {
list.remove();
}
// 唤醒其他所有线程
full.signalAll();
empty.signalAll();
// 释放锁
lock.unlock();
}
}
【2】生产者/消费者(BlockingQueue阻塞队列方法)
public class Storage
{
// 仓库最大存储量
private final int MAX_SIZE = 100;
// 仓库存储的载体
private LinkedBlockingQueue list = new LinkedBlockingQueue(100);
// 生产num个产品
public void produce(int num) {
// 如果仓库剩余容量为0
if (list.size() == MAX_SIZE) {
System.out.println("暂时不能执行生产任务!");
}
// 生产条件满足情况下,生产num个产品
for (int i = 1; i <= num; ++i) {
try {
// 放入产品,自动阻塞
list.put(new Object());
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 消费num个产品
public void consume(int num)
{
// 如果仓库存储量不足
if (list.size() == 0) {
System.out.println("暂时不能执行消费任务!");
}
// 消费条件满足情况下,消费num个产品
for (int i = 1; i <= num; ++i) {
try {
// 消费产品,自动阻塞
list.take();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
【3】观察者设计模式
public class SimpleObservable extends Observable{
private int data = 0;
public int getData(){
return data;
}
public void setData(int i){
if(this.data != i) {
this.data = i;
setChanged();
//只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。
notifyObservers();
}
}
}
public class SimpleObserver implements Observer{
public SimpleObserver(SimpleObservable simpleObservable){
simpleObservable.addObserver(this );
}
public void update(Observable observable ,Object data){ // data为任意对象,用于传递参数
System.out.println(“Data has changed to” + (SimpleObservable)observable.getData());
}
}
public class SimpleTest{
public static void main(String[] args){
SimpleObservable doc = new SimpleObservable ();
SimpleObserver view = new SimpleObserver (doc);
doc.setData(1);
doc.setData(2);
doc.setData(2);
doc.setData(3);
}
}
/*
*开发触发器
*/
--得到日期是周几
select to_char(sysdate+4,'DY','nls_date_language=AMERICAN') from dual;
select to_char(sysdate,'DY','nls_date_language=AMERICAN') from dual;
--建立BEFORE语句触发器
CREATE O
下面给大家整理了一些vim NERDTree的常用快捷键了,这里几乎包括了所有的快捷键了,希望文章对各位会带来帮助。
切换工作台和目录
ctrl + w + h 光标 focus 左侧树形目录ctrl + w + l 光标 focus 右侧文件显示窗口ctrl + w + w 光标自动在左右侧窗口切换ctrl + w + r 移动当前窗口的布局位置
o 在已有窗口中打开文件、目录或书签,并跳