微软实习生面试的2道算法题目
题目一
题目一有点类似于leetcode中的旋转数组那一系列题目https://leetcode-cn.com/problems/search-rotate-array-lcci/solution/xuan-zhuan-shu-zu-cong-yi-dao-nan-ge-ge-dcv7a/,考察二分。面试官将题目变形为V型或倒V数组找最小值的下标,具体题目如下。
- 题目:在一个数组中,元素是有序的,至多出现一个拐点,让我们求出数组中的最小值的下标。
- 对题目理解:题目是面试官口述,有些具体细节可以自己加上,我的理解主要就是分为4中情况,数组是单调递增、单调递减、凹型的V数组,凸型的倒V数组。室友和面试管交流过程中,让其查找的时间复杂度O(nlogn)——>O(n)——>O(logn),也就是最终要使用二分的方法做出来。我的理解是先判断出事以上4种情况的哪一个,然后进行处理,单调递增、单调递减、凸型的倒V数组这3种情况是可以直接得到答案,关键在于凹型的V数组的查找。我的做法是使用二分逼近最低点,如果mid在最低点直接返回,如果mid在左边下坡的,则令left=mid+1继续查找。如果mid在右边下坡的,则令right=mid-1继续查找,直到right等于left返回结果。
- 代码(Java)
public class Main {
public static void main(String[] args) {
int[] arr={4,2,3};
int len=arr.length-1;
if(len<3) System.out.println(arr[0]<arr[1]?0:1);
//判断凹凸性和线性的关系
if(arr[1]>arr[0]&&arr[len]>arr[len-1]){ //单调递增
System.out.println(0);
}else if(arr[1]<arr[0]&&arr[len]<arr[len-1]){ //单调递减
System.out.println(len);
}else if(arr[1]>arr[0]&&arr[len]<arr[len-1]){ //凸的
System.out.println(arr[0]<arr[len]?0:len);
}else if(arr[1]<arr[0]&&arr[len]>arr[len-1]){ //凹的
int left=0,right=len;
while (left<right){
int mid=left+(right-left)/2;
if(arr[mid]<arr[mid-1]&&arr[mid]<arr[mid+1]){
System.out.println(mid);
return;
}else if(arr[mid]<arr[mid-1]&&arr[mid]>arr[mid+1]){
left=mid+1;
}else if(arr[mid]>arr[mid-1]&&arr[mid]<arr[mid+1]){
right=mid-1;
}
}
System.out.println(left);
}
}
}
题目二
- 二叉树中的最大路径和(leetcode中的原题https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/,难度hard)
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。
- 思路解法:
主要就是运用自底向上的递归的方法,自底向上的计算二叉树中的每一个节点的最大贡献值,并更新全局最大值。具体而言,就是在以该节点为根节点的子树中寻找以该节点为起点的一条路径,使得该路径上的节点值之和最大。
具体详细思路可以参考题解:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-leetcode-/ - 代码(Java):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int maxSum=Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
//递归解法,该递归函数返回的
maxValue(root);
return maxSum;
}
public int maxValue(TreeNode node){
if(node==null){
return 0;
}
//递归计算左右子节点的最大贡献值,只有在最大贡献值大于 0 时,才会选取对应子节点
int leftValue=Math.max(maxValue(node.left),0);
int rightValue=Math.max(maxValue(node.right),0);
//节点的最大路径和取决于该节点的值、该节点的左右子节点的最大贡献值
int lmr=node.val+leftValue+rightValue;
int ret=node.val+Math.max(leftValue,rightValue);
maxSum=Math.max(maxSum,Math.max(lmr,ret));
return ret;
}
}