問題1: 在陣列中,數字減去他的右邊的數字得到乙個數對之差,求所有數對之差的最大值。 例如陣列中,數對之差的最大值是11,是16減去5的結果。
問題2:給定乙個含有n 個元素的數列,元素有正有負,找出和最小的一組相鄰的書,既給定a[n],是的a[i]+a[i+1]+...+a[j]的和最小。
先看第一道題目:
如果從頭遍歷,遍歷到某乙個位置,從這個位置開始遍歷到陣列結束,看此元素的數對只差的最帶值,然後更行當前的數對之差的最大值,o(n^2)的事件複雜度。
解法二:轉化成求解子陣列的最大和問題
接下來再介紹一種比較巧妙的解法。如果輸入乙個長度為
n的陣列
numbers
,我們先構建乙個長度為
n-1的輔助陣列
diff
,並且diff[i]
等於numbers[i]-numbers[i+1]
(0<=i)。如果我們從陣列
diff
中的第i
個數字一直累加到第
j個數字(
j > i
),也就是
diff[i] + diff[i+1] + … + diff[j] = (numbers[i]-numbers[i+1]) + (numbers[i + 1]-numbers[i+2]) + ... + (numbers[j] – numbers[j + 1]) = numbers[i] – numbers[j + 1]。
分析到這裡,我們發現原始陣列中最大的數對之差(即numbers[i] – numbers[j + 1])其實是輔助陣列diff中最大的連續子陣列之和。
int maxdiff_solution2(int numbers,unsigned length)
if(numbers == null || length < 2)
return 0;
int* diff = new
int[length - 1];
for(int i = 1; i < length; ++i)
diff[i - 1] = numbers[i - 1] - numbers[i];
int currentsum = 0;
int greatestsum = 0x80000000;
for(int i = 0; i < length - 1; ++i)
if(currentsum <= 0)
currentsum = diff[i];
else
currentsum += diff[i];
if(currentsum > greatestsum)
greatestsum = currentsum;
delete diff;
return greatestsum;
解法三:動態規劃法
既然我們可以把求最大的數對之差轉換成求子陣列的最大和,而子陣列的最大和可以通過動態規劃求解,那我們是不是可以通過動態規劃直接求解呢?下面我們試著用動態規劃法直接求數對之差的最大值。
我們定義diff[i]是以陣列中第i個數字為減數的所有數對之差的最大值。也就是說對於任意h(h < i),diff[i]≥number[h]-number[i]。diff[i](0≤i)的最大值就是整個陣列最大的數對之差。
假設我們已經求得了diff[i],我們該怎麼求得diff[i+1]呢?對於diff[i],肯定存在乙個h(h < i),滿足number[h]減去number[i]之差是最大的,也就是number[h]應該是number[i]之前的所有數字的最大值。當我們求diff[i+1]的時候,我們需要找到第i+1個數字之前的最大值。第i+1個數字之前的最大值有兩種可能:這個最大值可能是第i個數字之前的最大值,也有可能這個最大值就是第i個數字。第i+1個數字之前的最大值肯定是這兩者的較大者。我們只要拿第i+1個數字之前的最大值減去number[i+1],就得到了diff[i+1]。
int maxdiff_solution3(int numbers,unsigned length)
if(numbers == null || length < 2)
return 0;
int max = numbers[0];
int maxdiff = max - numbers[1];
for(int i = 2; i < length; ++i)
if(numbers[i-1] > max)
max = numbers[i-1];
int currentdiff = max - numbers[i];
if(currentdiff > maxdiff)
maxdiff = currentdiff;
return maxdiff;
在上述**中,max表示第i個數字之前的最大值,而currentdiff表示diff[i](0≤i),diff[i]的最大值就是**中maxdiff。轉換思維非常的重要。
上述是解決第乙個問題的方法,至於第二個問題,求出連續陣列的最小和。如果我們設定乙個輔助陣列,是的這個陣列為b[n]
b[0] = a[0], b[1] = a[0]+a[1] b[2] = a[0]+a[1]+a[2] b[3] = a[0]+a[1]+a[2]+a[3] b[i] = a[0]+a[1]+...+a[i] b[n] = a[0]+a[1]+.....+a[n]
那麼 a[i]+a[i+1]+......+a[j] = b[j]-b[i-1] 也就是說求得乙個連續序列的最小和就相當於求得b[n]陣列中的數對之差的最小值。
這麼一來就相當於第乙個問題了,其中s是輔助陣列
j = 1; i = 0; max = 0;
for (i=1; is[i] ? i : max;
}
這個演算法的思想是: s[i] 肯定是 s[j] 之前最大的數,s[j] 也是 s[i] 之後最小的數,那麼保留到目前為止最大的數 s[max],用當前數 s[i] 去減它(肯定是小於 s[i] - s[i] 的),看它是否小於 s[j] - s[i],如果是的話,那麼 s[i] -s[max] 就是到 i 為止最小的差值對。掃瞄一遍 s[n] 就能得到結果,o(n)!
這裡只不過是使用了最大元素的下標!
數對之差的最大值
題目 在陣列中,數字減去它右邊的數字得到乙個數對之差。求所有數對之差的最大值。例如在陣列中,數對之差的最大值是11,是16減去5的結果。static int maxdiff int arr if arr.length 2 arr null return 0 int max arr 0 intmaxd...
數對之差的最大值
題目 在陣列中,數字減去它右邊的數字得到乙個數對之差。求所有數對之差的最大值。例如在陣列中,數對之差的最大值是11,是16減去5的結果。分析 看到這個題目,很多人的第一反應是找到這個陣列的最大值和最小值,然後覺得最大值減去最小值就是最終的結果。這種思路忽略了題目中很重要的一點 數對之差是乙個數字減去...
數對之差的最大值 演算法
題目 在陣列中,數字減去它右邊的數字得到乙個數對之差。求所有數對之差的最大值。例如在陣列中,數對之差的最大值是11,是16減去5的結果。分析 看到這個題目,很多人的第一反應是找到這個陣列的最大值和最小值,然後覺得最大值減去最小值就是最終的結果。這種思路忽略了題目中很重要的一點 數對之差是乙個數字減去...