题目:
https://www.nowcoder.com/practice/8397609ba7054da382c4599d42e494f3?tpId=49&&tqId=29364&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking
现定义数组单调和为所有元素i的f(i)值之和。这里的f(i)函数定义为元素i左边(不包括其自身)小于等于它的数字之和。请设计一个高效算法,计算数组的单调和。
给定一个数组A同时给定数组的大小n,请返回数组的单调和。保证数组大小小于等于500,同时保证单调和不会超过int范围。
测试样例:
[1,3,5,2,4,6],6
返回:27
代码:
class MonoSum {
public:
//解法二:归并排序
int count = 0;
void Merge(vector<int> &A, int begin, int end, int middle) {
if (begin >= end)
return;
int left_index = begin, right_index = middle + 1;
vector<int> tem;
while (left_index <= middle && right_index <= end) {
if (A[left_index] <= A[right_index]) {
count += (end - right_index + 1)*A[left_index];
tem.push_back(A[left_index]);
left_index++;
}
else {
tem.push_back(A[right_index]);
right_index++;
}
}
for (int i = left_index; i <= middle; i++)
tem.push_back(A[i]);
for (int i = right_index; i <= end; i++)
tem.push_back(A[i]);
for (int i = begin; i <= end; i++)
A[i] = tem[i-begin];
}
void mergeSort(vector<int> &A, int begin, int end) {
int middle = (begin + end) / 2;
if (begin < middle)
mergeSort(A, begin, middle);
if (end > middle + 1)
mergeSort(A, middle + 1, end);
Merge(A, begin, end, middle);
}
int calcMonoSum(vector<int> A, int n) {
if (n < 2)
return 0;
mergeSort(A, 0, n - 1);
cout << count << endl;
system("pause");
return count;
}
//解法一
/*
int calcMonoSum(vector<int> A, int n) {
if (n == 1)
return A[0];
int result = 0;
for(int i=0; i<n; i++)
result += count_num(A, n, i) * A[i];
return result;
}
int count_num(vector<int> &A, int n, int i){
int count= 0;
for(int j = i+1; j<n; j++)
if(A[j] >= A[i])
count++;
return count;
}
*/
};
解法三:动态规划
class MonoSum {
public:
int calcMonoSum(vector<int> A, int n) {
int *dp = new int[n];
for (int i = 0; i<n; i++)
dp[i] = 0;
for (int i = 1; i<n; i++) {
for (int j = 0; j<i; j++) {
if (A[j] <= A[i]) {
if (dp[i] <= dp[j] + A[j])
dp[i] = dp[j] + A[j];
else
dp[i] = dp[i] + A[j];
}
}
}
int res = 0;
for (int i = 0; i<n; i++)
res = res + dp[i];
cout << res << endl;
return res;
}
};