-2

Today i got stuck on the following problem.Kindly provide some clues, the statement is following:

Given an array A[] of size n. Maximize A[i]*A[j]*A[k] under the following constraints:

  • i < j < k
  • A[i] < A[j] < A[k]

The code which i tried is as follow:

#include<iostream>
using namespace std;

int main(){
  int A[]={1,3,6,8,9};
  int max=0;
  int n=sizeof(A)/sizeof(A[0]);
  for(int i=0;i<n;i++)
      for(int j=i+1;j<n;j++)
        for(int k=j+1;k<n;k++)
        {
          if(A[i]<A[j]&&A[j]<A[k]&&max<A[i]*A[j]*A[k])
            max=A[i]*A[j]*A[k];
        }
        cout<<max;
   return 0;
}
braX
  • 11,506
  • 5
  • 20
  • 33

3 Answers3

1

Given i < j < k and you wanted to do something with 3 for loops, then you can obviously do

for(i = 0; i < n; ++i) {
    for(j = i + 1; j < n; ++j){
         if (A[i] < A[j]) {
             for(k = j + 1; k < n; ++k){
                 if(A[j] < A[k]) {
                 /*DoSomething with i,j,k*/
                 }
            }
         }
    }
}

This is mostly an indentation nightmare more than anything.

AlexG
  • 1,091
  • 7
  • 15
  • A constraint is `A[i] < A[j]`, so you can do `for ( j = i + 1 ; j < n ; ++j ) if ( A[i] < A[j] ) for ( k = j + 1 ; k < n ; ++k ) { /* do something */ }` – max66 Mar 06 '17 at 18:05
  • @max66 the time complexity of this solution is O(n^3) right.if yes then this is not efficient one.interviewer asked to do better. – Rahul Choudhary Mar 06 '17 at 18:17
  • @max66 Updated, thanks. This is only O(n^3) in the worst-case scenario (i = 0, j = 0, k = 0), in other cases it will be faster than that. – AlexG Mar 06 '17 at 18:21
  • @AlexG yes u r rt but can we do this in something like O(nlogn) or O(n^2)? – Rahul Choudhary Mar 06 '17 at 18:31
  • @Rahul - yes: also with my suggestion, remain O(n^3). – max66 Mar 06 '17 at 19:18
1

The following solution should be O(n^2)

#include <stack>
#include <iostream>
#include <stdexcept>

template <typename T>
std::stack<T> getStack (T const * a, std::size_t dimA)
 {
   if ( nullptr == a )
      throw std::runtime_error("nullptr in getStack()");

   if ( 0U == dimA )
      throw std::runtime_error("no values in getStack()");

   T              top;
   std::stack<T>  s;
   std::size_t    pos{ 0U };

   s.push(top = a[pos]);

   do
    {
      if ( top < a[pos] )
         s.push(top = a[pos]);
    }
   while ( ++pos < dimA );

   return s;
 }


int main()
 {
   int          a[] { 34, 12, 3, 7, 29, 45 };
   std::size_t  dimA { sizeof(a)/sizeof(a[0]) };
   std::size_t  numMult { 3U };


   std::stack<int> s;

   std::size_t     pos { 0U };

   do
    {
      s = getStack(a+pos, dimA - pos);
    }
   while ( (s.size() < numMult) && (numMult <= (dimA - ++pos)) );

   if ( s.size() < numMult )
      std::cout << "there is no solution" << std::endl;
   else
    {
      int res { s.top() };

      for ( auto ui = 1U ; ui < numMult ; ++ui )
       {
         s.pop();

         res *= s.top(); 
       }

      std::cout << "the solution is " << res << std::endl;
    }

   return 0;
 }
max66
  • 65,235
  • 10
  • 71
  • 111
1

There is a simple O(N^2) algorithm. Here is the outline:

  1. For each element y
  2. Search maximum element x which is smaller than y and before y
  3. Search maximum element z which is larger than y and after y

Step 1 is O(N), Step 2 & 3 can be done in same loop which is O(N), in total it is O(N^2)


There is a O(N lg N) algorithm too, but it is more complicated:

We can precompute in O(N) and query in O(1) for finding maximum in range [l,r]. (Original thought is use segment tree or any RMQ structures, thanks for @PetarPetrovic pointing out)

Also we build a set (sorted list) on the fly while we iterate through each element in the array. The pseudo code is like:

Array A = []
Set S = {}
Ans = 0

For i = 0 to N // O(N)
  // A[i] is y
  x = binary search S, maximum element in S which is < A[i] //O(lg N)
  z = RMQ(i+1, N) // O(lg N), or O(1) if we precompute in O(N)
  if(x < A[i] && A[i] < z) Ans = Max(Ans, x*A[i]*z)
  Insert A[i] into S // O(lg N)
//Total is O(N lg N)      

We try to see A[i] as the middle element y.

As we have a sorted set which contains all elements before i, we can binary search the maximum valid x using the set. We insert current element into this set afterwards.

We use O(N) to precompute an array and query in O(1) to find maximum in range [i+1, N-1]. The number found is z.

We update answer if (x,y,z) is valid tuple and greater than current answer.

shole
  • 4,046
  • 2
  • 29
  • 69
  • 1
    If you only want to find max in range [i + 1, N - 1], I think it can be done in O(n) prepossess and O(1) query time – Petar Petrovic Mar 07 '17 at 07:59
  • @PetarPetrovic Yea you are right, over thought, it's still O(N lg N) though :) – shole Mar 07 '17 at 07:59
  • @shole thanks for suggesting such efficient solution,this is is the exact approach that was pointed by the interviewer as hint ,but i could not able to understood at that time badluck... – Rahul Choudhary Mar 07 '17 at 15:09
  • Wont work for -ve numbers – ImBatman Nov 28 '22 at 07:32
  • @ImBatman yes you are right but it can easily handled by splitting into 4 cases, given the fact that x < y < z. Case 1 & 2: (+,+,+), (-,-,-), the answer will be max(x) * y * max(z) which is current algorithm. Case 3: (-,-,+) the answer will be min(x)*y*max(z). Case 4: (-,+,+) the answer will be max(x)*y*min(z). In coding, one can simply find minimum of x and z as well and just test all outcome of x * y * z to find the maximum – shole Dec 02 '22 at 04:23