最大子数组和
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组是数组中的一个连续部分。
解析
假设 nums 数组的长度是 n,下标从 0 到 n−1。
我们用 f(i) 代表以第 i 个数结尾的「连续子数组的最大和」,那么很显然我们要求的答案就是:
max0≤i≤n−1{f(i)}
因此我们只需要求出每个位置的 f(i),然后返回 f 数组中的最大值即可。那么我们如何求 f(i) 呢?我们可以考虑 nums[i] 单独成为一段还是加入 f(i−1) 对应的那一段,这取决于 nums[i] 和 f(i−1)+nums[i] 的大小,我们希望获得一个比较大的,于是可以写出这样的动态规划转移方程:
f(i)=max{f(i−1)+nums[i],nums[i]}
不难给出一个时间复杂度 O(n)、空间复杂度 O(n) 的实现,即用一个 f 数组来保存 f(i) 的值,用一个循环求出所有 f(i)。考虑到 f(i) 只和 f(i−1) 相关,于是我们可以只用一个变量 pre 来维护对于当前 f(i) 的 f(i−1) 的值是多少,从而让空间复杂度降低到 O(1),这有点类似「滚动数组」的思想。
class Solution {
public int maxSubArray(int[] nums) {
int pre=0,maxAns=Integer.MIN_VALUE;
for(int x:nums){
pre=Math.max(pre+x,x);
maxAns=Math.max(pre,maxAns);
}
return maxAns;
}
}
合并区间
以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
class Solution {
public int[][] merge(int[][] intervals) {
if (intervals.length == 0) {
return new int[0][2];
}
Arrays.sort(intervals, new Comparator<int[]>() {
public int compare(int[] interval1, int[] interval2) {
return interval1[0] - interval2[0];
}
});
List<int[]> merged = new ArrayList<int[]>();
for (int i = 0; i < intervals.length; ++i) {
int L = intervals[i][0], R = intervals[i][1];
if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {
merged.add(new int[]{L, R});
} else {
merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R);
}
}
return merged.toArray(new int[merged.size()][]);
}
}
轮转数组
给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[(i + k) % n] = nums[i];
}
System.arraycopy(arr, 0, nums, 0, n);
}
}
除自身以外数组的乘积
给你一个整数数组 nums
,返回 数组 answer
,其中 answer[i]
等于 nums
中除 nums[i]
之外其余各元素的乘积 。
题目数据 保证 数组 nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法,且在 O(n)
时间复杂度内完成此题。
class Solution {
public int[] productExceptSelf(int[] nums) {
int n=nums.length;
int[] pre1 = new int[nums.length];
int[] pre2 = new int[nums.length];
pre1[0] = 1;
for (int i = 1; i < nums.length; i++) {
pre1[i] = nums[i - 1] * pre1[i - 1];
}
pre2[n - 1] = 1;
for (int i = n - 2; i >= 0; i--) {
pre2[i] = nums[i + 1] * pre2[i + 1];
}
for (int i = 0; i < nums.length; i++) {
nums[i] = pre1[i] * pre2[i];
}
return nums;
}
}