面试题68 - I. 二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
//非递归
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root!=null){
if(p.val<root.val && q.val<root.val)
root = root.left;
else if(p.val>root.val && q.val>root.val)
root = root.right;
else
break;
}
return root;
}
//递归
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(p.val<root.val && q.val<root.val)
return lowestCommonAncestor(root.left,p,q);
if(p.val>root.val && q.val>root.val)
return lowestCommonAncestor(root.right,p,q);
return root;
}
面试题66. 构建乘积数组
给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
public int[] constructArr(int[] a) {
int [] res = new int[a.length];
int left = 1;
for(int i=0; i<a.length; i++){
res[i] = left;
left *= a[i];
}
int right = 1;
for(int j=a.length-1; j>=0; j--){
res[j] *= right;
right *= a[j];
}
return res;
}
面试题64. 求1+2+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
public int sumNums(int n) {
//(1+n)*n/2 最简单的了
//但是我用递归 哈哈
if(n==0) return 0;
return n+sumNums(n-1);
}
面试题63. 股票的最大利润
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
public int maxProfit(int[] prices) {
int left=0,right=1,res=-1;
while (right<prices.length){
res = res>prices[right]-prices[left]?res:prices[right]-prices[left];
if(prices[right]<prices[left])
left = right;
right++;
}
return res>0?res:0;
}
面试题62. 圆圈中最后剩下的数字
0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
public int lastRemaining(int n, int m) {
int p=0;
for(int i=2;i<=n;i++)
{
p=(p+m)%i;
}
return p;
}
面试题61. 扑克牌中的顺子
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
public boolean isStraight(int[] nums) {
Arrays.sort(nums);
int zero = 0, i=0;
for(; nums[i]==0 ;i++) if(nums[i]==0) zero++;
while(i<4 && nums[i]+1==nums[i+1]) {
i++;
}
if(i<4 && nums[i]==nums[i+1])
return false;
int j=4;
while(j>i && nums[j]-1==nums[j-1])
j--;
return nums[j]-nums[i]-1<=zero;
}
面试题60. n个骰子的点数
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
private int [] arr = new int[6*11+1];
public double[] twoSum(int n) {
dfs(0,0,n);
int num=0,sum=0, index=0;
for(int i=1; i<=66; i++)
if(arr[i]!=0){
num++;
sum += arr[i];
}
double []res = new double[num];
for(int i=1; i<=66; i++)
if(arr[i]!=0){
res[index++] = arr[i]*1.0/sum;
}
return res;
}
private void dfs(int k, int sum, int n) {
if(k==n){
arr[sum]++;
return;
}
for(int i=1; i<=6; i++)
dfs(k+1,sum+i,n);
}
面试题59 - II. 队列的最大值
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
private Queue<Integer> queue;
private Deque<Integer> maxQueue;
public MaxQueue() {
queue = new LinkedList<Integer>();
maxQueue = new LinkedList<Integer>();
}
public int max_value() {
if(maxQueue.isEmpty())
return -1;
return maxQueue.peek();
}
public void push_back(int value) {
queue.add(value);
while(!maxQueue.isEmpty() && maxQueue.peekLast()<=value)
maxQueue.pollLast();
maxQueue.add(value);
}
public int pop_front() {
if(queue.isEmpty())
return -1;
int res = queue.poll();
if(maxQueue.peekFirst()==res)
maxQueue.poll();
return res;
}
面试题59 - I. 滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums==null || nums.length==0) return new int[0];
int[] res = new int[nums.length - k + 1];
int max=nums[0],maxIndex=0,index = 0;//加上maxIndex能提高性能
int i=0,j=k-1;
for(int q=0; q<k; q++) {
if (nums[q] >= max){ // >= -> 加上maxIndex能提高性能
max = nums[q];
maxIndex = q;
}
}
while (j<nums.length-1){
res[index++] = max;
if(i==maxIndex){//最大值是左边界,从新寻找最大值
max=nums[i+1];maxIndex = i+1;
for(int q=i+2; q<=j+1; q++){
if (nums[q] >= max){
max = nums[q];
maxIndex = q;
}
}
}else{
if(nums[j+1]>=max){
max = nums[j+1];
maxIndex = j+1;
}
}
i++;j++;
}
res[index++] = max;
return res;
}
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums==null || nums.length==0) return new int[0];
int[] res = new int[nums.length - k + 1];
//大顶堆
PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> b - a);
int i=0, j=k-1, index=0;
for(int q=0; q<k; q++) queue.add(nums[q]);
while(j<nums.length-1){
res[index++] = queue.peek();
queue.remove(nums[i++]);
queue.add(nums[++j]);
}
res[index++] = queue.peek();
return res;
}