如何在数组中获取ascender元素?

时间:2012-03-07 05:06:58

标签: arrays

考虑N个整数的零索引数组A.该数组的指数是从0到N-1的整数。取一个指数K. 如果A [J]>,则将索引J称为K的上升者。 A [K]。注意,如果A [K]是数组A中的最大值,则K没有上升。 如果abs(K-J)是最小可能值(即,如果J和K之间的距离最小),则K的上升J被称为K的最接近的上升。 请注意,K最多可以有两个最接近的上升部分:一个较小,一个比K大。

7 个答案:

答案 0 :(得分:2)

这是一个C ++解决方案,其复杂性为O(n)。 注意,有两个循环但是每次迭代时元素的数量变为1/2,或者搜索范围上升了x2倍。 例如,第一次迭代需要N次,但第二次迭代已经是N / 2.

vector<long> ascender(vector <long> A)
{
    long N = A.size();
    vector<long> R(N,0);
    vector<long> IndexVector(N,0); //This vector contains the index of elements with R=0
    vector<long> RangeVector(N,0); //This vector define the loop range for each element
    IndexVector[N-1]=N-1;
    unsigned long CompxTest = 0;


    for (long counter=0;counter<N;counter++)
    {
        IndexVector[counter] = counter; // we start that all elements needs to be consider
        RangeVector[counter] = 1; // we start by looking only and neighbors
    }

    long Length = N;
    long range;

    while (Length>1)
    {
        long index = 0;
        cout<<endl<<Length;
        long J;

        for (long counter=0;counter<Length;counter++)
        {

            CompxTest++; // Just to test complexity

            J = IndexVector[counter]; // Get the index that need to be consider
            range = RangeVector[J];

            //cout<<" ("<<A[J]<<","<<J<<")";

            if (range > N)
            {
                cout<<endl<<"Mini assert "<<range<<" N "<<N;
                break;
            }

            if (J<(N-range) && A[J+range] > A[J])
            {
                R[J] = range;
            }

            if (J<(N-range) && A[J+range] < A[J] && R[J+range]==0)
            {
                R[J+range] = range;
            }



            if (J<(N-range) && A[J] == A[J+range] && R[J+range]==0)
            {
                R[J+range] = - range;

            }

            if (R[J]==0) // Didn't find ascender for this element - need to consider in next iteration
            {
                if (R[J+range]>2)  //We can increase the range because the current element is smaller
                    RangeVector[J] += R[J+range]-2;
                if (R[J+range]<-2)
                    RangeVector[J] += -R[J+range]-2;
                RangeVector[J]++;

                IndexVector[index] = J;
                index++;
            }
        }


        Length = index;

    }

    for (long counter=0;counter<N;counter++)
    {
        if (R[counter] < 0)
        {
            unsigned Value = abs(R[counter]);
            if (counter+Value<N && A[counter]<A[counter+Value])
                R[counter] = Value;

            if (counter > Value && R[counter-Value]==0)
                R[counter] = 0;

            R[counter] = Value + R[counter-Value];

            if (counter > Value && Value < R[counter - Value])
            {
                 long PossibleSolution = R[counter - Value] + Value;
                 if (PossibleSolution <N && A[PossibleSolution]>A[counter])
                     R[counter] = abs(counter - PossibleSolution);

            }


        }
    }

    cout<<endl<<"Complex "<<CompxTest;

    return R;

}

答案 1 :(得分:1)

//
// C++ using multimap. -- INCOMPLETE
// The multimap MM is effectively the "inverse" of the input array AA
// since it is ordered by pair(value, index), where index refers to the index in 
// input array AA, and value is the value in AA at that index. 
// Input AA is of course ordered as (index, value).
// So when we read out of MM in value order, (a sorted set of values), each value
// is mapped to the index in the original array AA.
//
int ascender(int AA[], int N, int RR[]) {

    multimap<int, int> MM;

// simply place the AA array into the multimap
    int i;
    for (i = 0; i < N; i++) {
        int value = AA[i];
        int index = i;
        MM.insert(make_pair(value, index));
    }

// simply read the multimap in order,
//  and set output RR as the distance from one value's
// original index to the next value's original index.
// 
// THIS code is incomplete, since it is wrong for duplicate values.
//
    multimap<int, int>::iterator pos;
    for (pos = MM.begin(); pos != MM.end(); ++pos) {
        int value = pos->first;
        int index = pos->second;
        ++pos;//temporarily move ahead to next item 
// NEED to FURTHER CONSIDER repeat values in setting RR
        RR[index] = (pos)->second - index;
        --pos;
    }


    return 1;
}

答案 2 :(得分:0)

        1. Sort the array (if not pre-sorted)
        2. Subtract every element with its adjacent element and store result in another 
           array.
           Example: 1 3 5 6 8 -----> (after subtraction) 2 2 1 2
        3. Find the minimal element in the new array.
        4. Device a logic which would relate the minimal element in the new array to the 
           two elements in the original one.

答案 3 :(得分:0)

public class Solution {
    final static int MAX_INTEGER = 2147483647;

    public static int maximal(int[] A) {
        int max = A[0];
        int length = A.length;
        for (int i = 1; i < length; i++) {
            if (A[i] > max) {
                max = A[i];
            }
        }
        return max;
    }

public static int ascender(int[] a,int length, int k) {
    int smallest = MAX_INTEGER;
    int index = 0;

    if (k<0 || k>length-1) {
        return -1;
    }
    for (int i = 0; i < length; i++) {
        // Index J is called an ascender of K if A[J] > A[K]. 
        if(a[i] > a[k]) {
            int abs = Math.abs(i-k);
            if ( abs < smallest) {

                smallest = abs;

                index = i;
            }
        }
    }
    return index;
}


public static int[] array_closest_ascenders(int[] A) {

    int length = A.length;
    int[] R = new int[length];

    for (int K = 0; K < length; K++) {

        // Note that if A[K] is a maximal value in the array A, 
                    // then K has no ascenders.
        // if K has no ascenders then R[K] = 0.
        if (A[K] == maximal(A)) {
            R[K] = 0;
            break;
        }

        // if K has the closest ascender J, then R[K] = abs(K-J);
        // that is, R[K] is equal to the distance between J and K
        int J = ascender(A, A.length, K);

        if (J != -1) {

            R[K] = Math.abs(K - J);
        }

    }
    return R;
}

public static void main(String[] args) {
    int[] a = { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
    /* int[] a = {-589630174, 806785750, -495838474, -648898313, 
            149290786, -798171892, 584782920, -288181260, -252589640, 
            133741336, -174886978, -897913872 }; */
    int[] R = array_closest_ascenders(a);

    for (int element : R) {
        System.out.print(element + " ");
    }
}
}

答案 4 :(得分:0)

关于代码的一些注意事项。我想break方法中的array_closest_ascenders应该被continue替换,以便分析所有元素的上升程度。
当然,maximal(A)必须被移出一个循环;而是在进入循环之前为某个变量分配最大值并在循环中使用它,从而避免冗余计算最大值。

答案 5 :(得分:0)

这是C#解决方案

 class Program
{
    static void Main(string[] args)
    {
        int[] A = new int[] { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
         int[] B = new int[A.Length];
        int[] R = new int[A.Length];
        Program obj = new Program();
        obj.ABC(A,B, R);
    }

    public void ABC(int[] A,int[]B, int[] R)
    {
        int i, j, m,k;
        // int temp = 0;
        int n = A.Length - 1;
        for (i = 0; i < n; i++)
        {
            for (j = 0; j <= n; j++)
            {
                if (A[i] < A[j])
                {
                    m = Math.Abs(j - i);
                    R[i] = m;
                    break;

                }

            }
            for (j = i-1; j > 0; j--)
            {
                if (A[i] < A[j])
                {
                    k = Math.Abs(j - i);
                    B[i] = k;
                    break;

                }

            }

        }
        for (i = 0; i < n; i++)
        {
            if (R[i] > B[i] && (B[i] == 0))
            {

                R[i] = R[i];
                //Console.WriteLine(R[i]);
                //Console.ReadLine();
            }

            else { R[i] = B[i]; }
        }


    }
}

答案 6 :(得分:0)

基本上在搜索功能中,我将数组的第一个元素与右边的元素进行比较,如果它更大,这意味着它是第一个最接近的上升元素。对于其他元素,我比较左边的一个元素,然后紧接着右边的元素。第一个更大的是最接近的上升,我继续这样迭代,直到我找不到比我正在考虑的元素大或我返回0的元素。

class ArrayClosestAscendent {
 public int[] solution(int[] A) {
     int i;
     int r[] = new int[A.length];
     for(i=0;i<A.length;i++){
         r[i] = search(A, i);
     }
     return r;
 }

public int search(int[] A, int i) {
    int j,k;
    j=i+1;
    k=i-1;
    int result = 0;
    if(j <= A.length-1 && (A[j]>A[i]))
            return Math.abs(j-i);
    j++;
     while(k>=0 || j < A.length){
         if(k >= 0 && A[k] > A[i]){
             return Math.abs(i-k);
         }else if(j < A.length && A[j] > A[i]){
             return Math.abs(i-j);
         }else{
             j++;
             k--;
         }
     }
     return result;
}
}