JZ30 连续子数组的最大和
(简单)
题目
描述
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n)。
示例
输入:
[1,-2,3,10,-4,7,2,-5]
返回值:
18
说明:
输入的数组为{1,-2,3,10,—4,7,2,一5},和最大的子数组为{3,10,一4,7,2},因此输出为该子数组的和 18。
思路
使用动态规划求解问题,最重要的就是确定从前一个阶段转化到后一个阶段之间的递推关系, 递推关系必须是从次小的问题开始到较大的问题之间的转化,从这个角度来说,动态规划往往可以用递归程序来实现,不过因为递推可以充分利用前面保存的子问题的解来减少重复计算,所以对于大规模问题来说,有递归不可比拟的优势,这也是动态规划算法的核心之处。
因此,此题已明确限定时间复杂度为 O(n),因此我们需要的首要任务是找清楚递推关系公式,同时,因为我们的时间复杂度只允许我们遍历一次数组,因此还需要用一个变量来记录最大的子数组和,而且,由于该方法传入的是引用型的数组变量,因此我们也要拷贝一份此数组,操作拷贝的那份,而不是直接操作传入的那份,如果不这样,那可能会在项目种产生十分严重的故障。而且我们也要考虑数组参数为 null 的情况,这时直接返回和为 0 即可,使程序有较好的健壮性。
我们令拷贝的那份数组的名为 arr ,arr[i](即数组中的第 i 个元素值) 的结果,根据 arr[i - 1] 推出,当 arr[i - 1] 为正数的时候,是可以促进待选子数组和变大的,因此要加上,即 arr[i] += arr[i - 1],若 arr[i - 1] 为负数,则将使得待选子数组和变小,因此不应该加上,应舍弃 [0,i-1] 下标范围内的数组元素,令 arr[i] += 0 即可,也就是从当前数组元素再次作为起始元素开始,并在每次进行上述求 arr[i] 的操作之后,用一个变量 max 来记录下 arr[i] 的最大值即可,这样就可以巧妙高效地选取出,最后变量 max 就正是和最大的子数组元素值的和。
实现
public class JZ30连续子数组的最大和 {
public int FindGreatestSumOfSubArray(int[] array) {
if (array == null) {
return 0;
}
int[] arr = new int[array.length];
System.arraycopy(array, 0, arr, 0, arr.length);
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
arr[i] += arr[i - 1] > 0 ? arr[i - 1] : 0;
max = Math.max(max, arr[i]);
}
return max;
}
}
JZ4 重建二叉树
(中等)
题目
描述
给定某二叉树的前序遍历和中序遍历,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。
提示:
1.0 <= pre.length <= 2000
2.vin.length == pre.length
3.-10000 <= pre[i], vin[i] <= 10000
4.pre 和 vin 均无重复元素
5.vin出现的元素均出现在 pre里
6.只需要返回根结点,系统会自动输出整颗树做答案对比
示例1
输入:
[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]
返回值:
{1,2,3,4,#,5,6,#,7,#,#,8}
说明:
返回根节点,系统会输出整颗二叉树对比结果
示例2
输入:
[1],[1]
返回值:
{1}
示例3
输入:
[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值:
{1,2,5,3,4,6,7}
思路
这次就偷个懒吧,只想写个代码实现,但不想自己再写思路了,碰巧有位大佬写的思路也非常清晰易懂,我对此题也没想到更巧妙的方法。
(下图来源)
实现
public class JZ4重建二叉树 {
public TreeNode reConstructBinaryTree(int[] pre,int[] in) {
if (pre == null || in == null
|| pre.length == 0 || in.length == 0) {
return null;
}
TreeNode root = new TreeNode(pre[0]);
for (int i = 0; i < in.length; i++) {
if (in[i] == pre[0]) {
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
break;
}
}
return root;
}
}