1. 程式人生 > >筆試面試演算法經典--連續子陣列的最大乘積及連續子陣列的最大和(Java)

筆試面試演算法經典--連續子陣列的最大乘積及連續子陣列的最大和(Java)

1. 子陣列的最大和

輸入一個整形陣列,數組裡有正數也有負數。陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。求所有子陣列的和的最大值。例如陣列:arr[]={1, 2, 3, -2, 4, -3 } 最大子陣列為 {1, 2, 3, -2, 4} 和為8。

解法1(時間複雜度O(N * N)空間複雜度O(1))
求出所有的子陣列的和,比較選擇出最大值。利用雙重迴圈就可以遍歷到所有的子陣列。

public static void maxSum1(int arr[])
    {
        int max=0,sum;
        for(int i=0;i<arr.length
;i++) { sum=0; for(int j=i;j<arr.length;j++) { //遍歷陣列的所有子陣列,並將子陣列的最大和儲存在max中。 sum+=arr[j]; max=Math.max(max, sum); //max儲存最大的子陣列的和 } } System.out.println(max); }

解法2(動態規劃時間複雜度O(N)空間複雜度O(1))


遍歷陣列,用 sum 儲存子陣列的和,當 sum<0 時 將 arr[i] 賦值給 sum,用 max 儲存最大值。

 public static void maxSum(int arr[])
    {
        int max=0,sum=0;
        for(int i=0;i<arr.length;i++)
        {
            if(sum<=0)
            {
                sum=arr[i];
                //如果 sum<0 重新賦值
            }
            else
{ sum+=arr[i]; } max=Math.max(sum, max); //將最大值儲存在max中。 } System.out.println(max); }

2. 子陣列的最大乘積

輸入一個整形陣列,數組裡有正數也有負數。陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。求所有子陣列的和的最大值。例如陣列:arr[]={1, 2, 3, -2, 4, 3 } 最大子陣列為 {4,3} 積為12。

解法1(時間複雜度O(N * N)空間複雜度 O(1)):
跟上面求最大子陣列的和類似,利用雙重迴圈遍歷所有的子陣列,求出所有子陣列中值最大的。

public static void maxproduct(int arr[])
    {
        if(arr==null||arr.length==0)
            return;
            //如果陣列為 null 或者長度為0直接返回
        int max=0,product=1;
        //max儲存子陣列的最大乘積,product 用來儲存每一個子陣列的積
        for(int i=0;i<arr.length;i++)
        {       
            product=1;
            for(int j=i;j<arr.length;j++)
            {
                product*=arr[j];
                max=Math.max(product, max);
                //max儲存最大的子陣列乘積
                if(product==0)
                    break;
                //如果當前子陣列的乘積為0則以當前陣列為頭的後序陣列的積全為0不用求。
            }
        }
        System.out.println(max);
    }

解法2(動態規劃 時間複雜度O(N )空間複雜度 O(1)):

跟上面求最大子陣列的和類似,利用雙重迴圈遍歷所有的子陣列,求出所有子陣列中值最大的。以arr[i] 結尾的最大值可能由前面的以arr[i-1]結尾的 最大 負值,最大正數,和arr[i] 產生。例如陣列:{2,-3,-4}以-4結尾的最大值,就是3*2=-6,與-4 相乘產生的。

 public static void maxSubProduct(int arr[])
    {
        if(arr==null||arr.length==0)
            return ;
        int max=arr[0],min=arr[0],maxend,result=0;
        for(int i=1;i<arr.length;i++)
        {
            //最大值的來源有三種,如果arr[i]是正數,肯定與前面的最大值相乘得到最大值,
            //如果arr[i]是負數就會與前面的最小值相乘產生最大值。如果前面的為0或者負數,
            //arr[i]本身可能是最大值。
            maxend=Max(max*arr[i],min*arr[i],arr[i]);
            //maxend 儲存最大值
            min=Min(max*arr[i], min*arr[i], arr[i]);
            //用於儲存最小的負值,為下一個最大值最準備
            max=maxend; 
            result=Math.max(result, max);
        }
        System.out.println(result);
    }

  public static int Max(int a,int b,int c)
    {
    //返回 a b c 中的最大值
        a=Math.max(a, b);
        a=Math.max(a, c);
        return a;
    }
    public static int Min(int a,int b,int c)
    {
    //返回  a b c 中的最小值
        a=Math.min(a, b);
        a=Math.min(a, c);
        return a;
    }