1. 连续子数组的最大和
1.1 题目描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
1.2 示例1
输入
[1,-2,3,10,-4,7,2,-5]
返回值
18
1.3 核心代码实现
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int res = array[0];
int len = array.length;
int[] sum = new int[len];
sum[0] = res;
for(int i = 1; i < len; i++){
sum[i] = Math.max(array[i], sum[i-1] + array[i]);
res = Math.max(res, sum[i]);
}
return res;
}
}
2. 数组中的逆序对
2.1 题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
2.2 输入描述
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
2.3 示例1
输入
[1,2,3,4,5,6,7,0]
返回值
7
2.4 核心代码实现
public class Solution {
private int res;
public int InversePairs(int [] array) {
if(array == null || array.length == 0){
return -1;
}
Merge_Sort(array, 0, array.length - 1);
return res;
}
//先分后合,分:Merge_Sort(),合:Merge()
private void Merge_Sort(int [] array, int start, int end){
if(start >= end){
//归并结束条件,只有一个元素
return;
}
int mid = (start + end) / 2;
Merge_Sort(array, start, mid); //左归并
Merge_Sort(array, mid + 1, end); //右归并
Merge(array, start, end, mid); //排序统计
}
private void Merge(int [] array, int start, int end, int mid){
int [] temp = new int [end - start +1]; //辅助数组
int index = 0; //相当于temp数组指针,往数组添加新元素,向后移动
int p1 = start; //左边数组的起点
int p2 = mid + 1; //右边数组的起点
while(p1 <= mid && p2 <= end){
//比较p1和p2位置的元素,将较小的元素添加到temp
if(array[p1] <= array[p2]){
temp[index++] = array[p1++];
}else{
temp[index++] = array[p2++];
res += mid - p1 + 1;
res %= 1000000007;
}
}
//若左边全部添加到temp中后,则继续往temp添加右边
if(p1 > mid){
while(p2 <= end){
temp[index++] = array[p2++];
}
}
//若右边全部添加到temp中后,则继续往temp添加左边
if(p2 > end){
while(p1 <= mid){
temp[index++] = array[p1++];
}
}
//在原数组中用有序的值覆盖掉原来无序的值
for(int i = 0; i < temp.length; i++){
array[start + i] = temp[i];
}
}
}