什么是平衡二叉树?
答:有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return dfs(root)!=-1;
}
int dfs(TreeNode root)
{
if(root==null) return 0;
int left=dfs(root.left);
if(left==-1) return -1;
int right = dfs(root.right);
if(right==-1) return -1;
return Math.abs(left-right)>1 ? -1: Math.max(left,right)+1;
}
}
下面这种代码可以对比一下,没有进行减枝的
链接:https://www.nowcoder.com/questionTerminal/8b3b95850edb4115918ecebdf1b4d222?f=discussion
来源:牛客网
public classSolution {
public boolean IsBalanced_Solution(TreeNode root) {
if(root == null) {
return true;
}
return Math.abs(maxDepth(root.left) - maxDepth(root.right)) <= 1 &&
IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
}
private int maxDepth(TreeNode root) {
if(root == null) {
return 0;
}
return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
}
题目二
只出现一次的数
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
普通方法:使用HashMap 两次遍历,返回结果
普通法二: 排序一遍,使用栈,peek一下相同的就pop,不同的就push ,最终栈里只有两个值,
拿出来就是要的那个数
异或方法
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int aOrb = 0;
num1[0]=num2[0]=0;
for(int i:array) aOrb^=i;
int i=0;
for(;i<31;++i)
{
if((aOrb&(1<<i))!=0) break;
}
int flag = 1<<i;
for(int j:array) {
if((j&flag)==0)
{
num1[0]^=j;
}else{
num2[0]^=j;
}
}
}
}
这个题我解释一下,一个数和数组里的所有数异或,由于数组里只有两个数的不一样的,因此这个数的值等于 num1[0]^num2[0],思考一下,异或两次得到0哦,0与任何数异或都等于那个数,自己画个图想一下
num1[0]与num2[0]不一样,那么异或之后的二进制数一定有个值为1,(举个例子,i等于j,i^j==0;)(如果i!=j ,那么 i异或j一定不等于0),也就是说,相同异或为0,不同异或为1,只要找到不同,就能区分开个两个数,用两个桶分别装起来
因此,利用二进制数1的位置不同,可以区分 Num1和Num2
题目三
和为S的连续正数
时间复杂度不知怎么分析,估计不会是 O(N^2), 因为是等差数列
N
∗
(
N
+
1
)
/
2
=
s
u
m
N*(N+1)/2=sum
N∗(N+1)/2=sum , 所以 N<
2
∗
s
u
m
\sqrt{2*sum}
2∗sum
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
int sum;
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
this.sum = sum;
ArrayList<ArrayList<Integer>> ans = new ArrayList();
//等差数列: N*(A中) = sum, 关键是求 (A中),求中间那个数
//注意到 N*(N+1)= 2* sum ,因此N是有个上界的,
if(sum<=1)
{
return ans;
}
int bound = (int)Math.sqrt(sum<<1);
for(int i=1;i<bound;++i)
{
int mid = sum/i;
if((i&1)==1)
{
ArrayList p = getOdd(mid,false);
if(!p.isEmpty()) ans.add(p);
}else{
ArrayList p = getOdd(mid,true);
if(!p.isEmpty()) ans.add(p);
}
}
Collections.sort(ans,(ArrayList<Integer> a,ArrayList<Integer> b)->{return a.get(0).compareTo(b.get(0));});
return ans;
}
public ArrayList<Integer> getOdd(int mid,boolean even)
{
ArrayList<Integer> res = new ArrayList();
if(mid==sum)
{
return res;
}
int l = mid-1,r = mid+1;
if(even) ++l;
int sq = l+r+mid;
if(even) sq-=mid;
while(sq<=sum)
{
if(sq==sum)
{
for(int i=l;i<=r&&(i>0);++i)
{
if(i==0) continue;
res.add(i);
}
return res;
}
l--;r++;
sq+=(l+r);
}
return res;
}
}
我看了一下,有一种双指针的写法,维护一个滑动窗口,窗口内的和小于sum,r++,窗口内的和大于sum,那么l++, 等于的话登记一下信息,再 l++(因为r++的话一定是大于sum的)
我也写一下
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
int sum;
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> ans = new ArrayList();
//等差数列: N*(A中) = sum, 关键是求 (A中),求中间那个数
//注意到 N*(N+1)= 2* sum ,因此N是有个上界的
if(sum<=1) return ans;
int l=1,r=2;
while(l<r)
{
//在内部使用等差数列的公式计算
int res = (r-l+1)*(l+r)>>>1;
if(res<sum) r++;
else if(res==sum)
{
ArrayList<Integer> arr = new ArrayList();
for(int i=l;i<=r;++i)
{
arr.add(i);
}
ans.add(arr);
l++;
}
else{
l++;
}
}
return ans;
}
}
题目四
和为S的数字
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] arr,int sum) {
// i+j=sum, 求 min(i*j),也就是i==j的时候, i*j最大, 如果ij相差越远就越小
int l=0,r=arr.length-1;
while(l<r)
{
int res = arr[l]+arr[r];
if(res>sum)
{
r--;
}
else if(res==sum)
{
ArrayList<Integer> p = new ArrayList<Integer>();
p.add(arr[l]);
p.add(arr[r]);
return p;
}else
{
l++;
}
}
return new ArrayList<Integer>();
}
}
题目五
左旋转字符串
题目描述
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它
public class Solution {
public String LeftRotateString(String str,int n) {
int len = str.length();
if(len<n) return "";
String ans = (str+str).substring(n,len+n);
return ans;
}
}