/********************************************************************

    purpose:    微軟筆試題

    求隨機(jī)數(shù)構(gòu)成的數(shù)組中找到長(zhǎng)度大于=3的最長(zhǎng)的等差數(shù)列
    輸出等差數(shù)列由小到大: 
    如果沒(méi)有符合條件的就輸出
    格式:
    輸入[1,3,0,5,-1,6]
    輸出[-1,1,3,5]
    要求時(shí)間復(fù)雜度,空間復(fù)雜度盡量小

 ********************************************************************
*/

#include 
<iostream>
#include 
<set>
#include 
<vector>

using namespace std;

// 歸并排序
void Merge(int rOrg[], int rBuf[], int from, int mid, int to)
{
    
int i = from;
    
int j = mid + 1;
    
int k = from;
    
while (i <= mid && j <= to)
    
{
        
if (rOrg[i] <= rOrg[j])
            rBuf[k
++= rOrg[i++];
        
else
            rBuf[k
++= rOrg[j++];
    }

    
if (i <= mid)
        
while (i <= mid)
            rBuf[k
++= rOrg[i++];
    
else
        
while (j <= to)
            rBuf[k
++= rOrg[j++];
    
while(k>from)
        rOrg[
--k] = rBuf[k];
}

// 歸并排序
void MergeSort(int r[], int rBuf[], int from, int to)
{
    
if (from == to)
        rBuf[from] 
= r[from];
    
else
    
{
        
int mid = (from + to) / 2;
        MergeSort(r, rBuf, from, mid);
        MergeSort(r, rBuf, mid 
+ 1, to);
        Merge(rBuf, r, from, mid, to);
    }

}

// 二分查找
int BinarySearch(int *r, const int &item, int left, int right)
{
    
int middle;
    
while(left <= right)
    
{
        middle    
= (left + right)/2;
        
if(r[middle] == item)
            
return    middle;
        
else if(r[middle] < item)
            left 
= middle + 1;
        
else
            right 
= middle - 1;
    }

    
return -1;
}


// 求隨機(jī)數(shù)構(gòu)成的數(shù)組中找到長(zhǎng)度大于=3的最長(zhǎng)的等差數(shù)列
void MaxLenEQDistSubArray(int rOrg[], int len) {
    
if (rOrg == NULL || len < 3{
        
return;
    }

    
int *rBuf = new int[len]; // 用于歸并排序
    MergeSort(rOrg, rBuf, 0, len-1);

    
int** steps = new int*[len];
    
int* stepP;
    
int i, j, k, jEnd, left, right=len-1,
        curDist, curLastItem, curLen
=0,
        maxDist, maxLastItem, maxLen
=2;

    
// 初始化 步數(shù)數(shù)組
    for (i = 0; i < len; i++{
        steps[i] 
= new int[len-i];
        stepP 
= steps[i];
        
for (int j = len-i-1; j >= 0; j-- ) {
            stepP[j] 
= 0;
        }

    }


    
// 開(kāi)始查找最大等差子數(shù)組
    
// i為等差第一項(xiàng)的位置 j為等差第二項(xiàng)位置
    for (i = 0; i < len; i++{
        jEnd 
= len - 1// 要求的等差數(shù)列最小長(zhǎng)度為3,等差第二項(xiàng)最大為原數(shù)組倒數(shù)第二項(xiàng)
        stepP = steps[i];
        
for (j = i + 1; j < jEnd; j++{
            
if (stepP[j-i-1]) // ① 此index步長(zhǎng)j-i己被前面②計(jì)算過(guò)
                continue;
            }

            
//stepP[j-i-1]=1; // 可省略,因?yàn)椴粫?huì)再訪問(wèn)這個(gè)標(biāo)志
            curLastItem = rOrg[j];
            curDist 
= rOrg[j]-rOrg[i]; // 本次等差
            left = j;
            curLen 
= 2;
            
while ((k=BinarySearch(rOrg, curLastItem+curDist, left+1, right)) != -1//是否存在下一等差數(shù)
                curLen++;
                curLastItem 
+= curDist;
                steps[left][k
-left-1= 1// ② 記錄 index為left位置 index步長(zhǎng)k-left 的數(shù)組己被前面計(jì)算過(guò)
                left = k;
            }

            
if (curLen > maxLen) // 記錄最大等差數(shù)列信息
                maxLen = curLen;
                maxLastItem 
= curLastItem;
                maxDist 
= curDist;
            }

            
        }

    }


    
// 輸出結(jié)果
    if (maxLen >= 3{
        
int start = maxLastItem - maxDist*(maxLen-1);
        cout
<<"max length:"<<maxLen<<endl;
        cout
<<"max sub array: ";
        
while(maxLen--)
        
{
            cout
<<start<<" ";
            start 
+= maxDist;
        }

        cout
<<endl;
    }
 else {
        cout
<<"no GT 3 length sub array"<<endl;
    }


    delete[] rBuf;
    delete[] steps;
}


void Test_MaxLenEQDistSubArray()
{
    
//// test MergeSort
    //const int LEN = 8;
    
//int rOrg[LEN]={10,3,5,1,9,34,54,565},rBuf[LEN];
    
//MergeSort(rOrg, rBuf, 0, LEN-1);
    
//for (int i = 0; i < LEN; i++)
    
//    cout << " " << rOrg[i];

    
int rOrg[] = {1,3,0,5,-1,6}//{1,3,0,5,-1,6}; {1,3,7,8,9,10,11,0,5,-1,6}; {1,3,7,8,9,10,11,12,0,5,-1,6}; {1,3,7,8,9,10,11,12,13,0,5,-1,6};
    MaxLenEQDistSubArray(rOrg, sizeof(rOrg)/sizeof(rOrg[0]));

    
{
        
int rOrg[] = {1,3,7,8,9,10,11,0,5,-1,6}
        MaxLenEQDistSubArray(rOrg, 
sizeof(rOrg)/sizeof(rOrg[0]));
    }

    
{
        
int rOrg[] = {1,3,7,8,9,10,11,12,0,5,-1,6}
        MaxLenEQDistSubArray(rOrg, 
sizeof(rOrg)/sizeof(rOrg[0]));
    }

    
{
        
int rOrg[] = {1,3,7,8,9,10,11,12,13,0,5,-1,6}
        MaxLenEQDistSubArray(rOrg, 
sizeof(rOrg)/sizeof(rOrg[0]));
    }


}