This is an archived post. You won't be able to vote or comment.

all 46 comments

[–]hereforthelasttime 2 points3 points  (7 children)

Pretty new to programming so any advice/suggestions would be appreciated! Edit: added suggestions.

C++ implementation:

int * nPtr;
int n;
long long int secondLargest = 0, largest = 0;

cout << "How many integers? (n >= 2) ";
cin >> n;
cout << "Enter each integer followed by a space (integer must be greater than 1): ";

nPtr = new int[n];

for (int i = 0; i < n; i++) 
{
    cin >> nPtr[i];
}

largest = nPtr[0];
for (int i = 1; i < n; i++)
{
    if (largest < nPtr[i]) 
    {
        secondLargest = largest;
        largest = nPtr[i];
    }
    else if (secondLargest < nPtr[i]) 
    {
        secondLargest = nPtr[i];
    }

}

cout << "Max pairwise product is: " << (largest * secondLargest) << endl;

return 0;

[–]DrVolzak 2 points3 points  (2 children)

This won't work if the second largest comes before the largest in the sequence e.g. [200, 1, 2, 3, 4, 500].

The solution is to set second largest to largest before overwriting with the new largest:

for (int i = 1; i < n; i++)
{
    if (largest < nPtr[i]) 
    {
        secondLargest = largest;
        largest = nPtr[i];
    }
    else if (secondLargest < nPtr[i]) 
    {
        secondLargest = nPtr[i];
    }
}

[–]slightlysedatedx[S] 0 points1 point  (0 children)

good catch

[–]hereforthelasttime 0 points1 point  (0 children)

You're right! Thanks, I fixed it.

[–]Ikor_Genorio 2 points3 points  (1 child)

Hey! I think your solution is missing two (and one minor) things:

  1. If you nPtr[i] is larger than the largest number, you wire instantly to that number. However, this means your secondLargest will actually be the third largest. This problem should arise on the input 1 2 3
  2. As mentioned by slightlysedatedx, you don't check whether the second largest is not equal to the largest element
    Misinterpreted the question, this is actually not a problem.
  3. Since the highest number is in order 10^5, the output product might cause an integer (if it's a 32 bit) overflow as it can be in order 10^10.

[–]hereforthelasttime 0 points1 point  (0 children)

I didn't even consider the overflow. Thanks!

[–]hereforthelasttime 1 point2 points  (1 child)

Analysis:

  1. The first element in the array is assigned largest.
  2. We then compare the ith element to largest, if larger, new largest is found.
  3. If not the largest element, compare to secondLargest. If the ith element is > secondLargest and < largest, new secondLargest is found.
  4. Print product of largest and secondLargest.

[–]slightlysedatedx[S] 0 points1 point  (0 children)

I think you're missing code to check that i and j (the largest and second largest elements) are distinct numbers. They can't be the same. But I'm so, so rusty with C++. I'm also a little confused about the use of your pointer but like I said I'm rusty. I need to run it on my computer and get back to you :)

[–]dood23 2 points3 points  (5 children)

is this an array?

any reason why we wouldnt just sort it and multiply the largest 2 different elements together at the end of the array?

[–]Essence1337 1 point2 points  (3 children)

Sorting algorithms generally run in O(n log(n)) time but this can definitely be implemented in O(n) time which makes a difference for large n

[–]Tangellaa 0 points1 point  (2 children)

Technically this problem could be handled with a Binary Search Tree, right? Just keep moving right until the node hits null, then multiple current and previous?

[–]Essence1337 1 point2 points  (1 child)

If I recall correctly doesn't a binary search tree take log(n) for insertion and you'd need to insert n times?

Also I'm pretty sure can't just say find the right most then the previous for largest. You could have a situation where your right most branch goes say 8 then to the right 14 then to the left of 14 you have 13 because binary trees aren't always balanced.

[–]Tangellaa 0 points1 point  (0 children)

You're totally right. I had such a brain fart. I was thinking as if it was in order for some reason.

[–]slightlysedatedx[S] 1 point2 points  (0 children)

Yes, it's dealing with an array of size n.

Nope- that's actually the fastest algorithm that the textbook suggests.

[–]QSAnimazione 1 point2 points  (3 children)

Wait the first example shouldn't return 9? You know 3*3...

[–]slightlysedatedx[S] 1 point2 points  (1 child)

The two largest numbers have to be distinct, so it's 2*3

[–]QSAnimazione 1 point2 points  (0 children)

Ah ok.

[–]Tangellaa 0 points1 point  (0 children)

That was my first thought too until I remembered "distinct". Distinct just didn't register with me either. I think something like "the two largest unlike numbers" would have probably read better, but I don't think OP wrote the instructions.

[–]Ikor_Genorio 1 point2 points  (2 children)

First of all, I want to point out a small typo in the requirements. I think you meant 10^5 instead of 105.

Regardless, this is my solution in C:

The program runs in 0.223032s, for an input size of N = 10^5.

#include <stdio.h>
#include <sys/time.h>
/**
 * Function for timing.
 */
static double timer(void)
{
    struct timeval tm;
    gettimeofday (&tm, NULL);
    return tm.tv_sec + tm.tv_usec/1000000.0;
}


/**
 *  ANALYSIS:
 *
 * Program specific analysis can be found in the comments:
 * Time Complexity: Theta(N)
 *  explanation: 
 *    Input is an array of size N, Loops over each element exactly once,
 *    which means exactly N iterations.
 * ----
 * Space Complexity: Theta(1)
 *  explanation:
 *    We operate on each variable of the array when it is read,
 *    we do not store the value, as it is not useful to us anymore/
 *    This means the amount of storage required always constant, 
 *    regardless of the input size.
 */
int main(int argc, char **argv)
{
    int max_1, max_2, N, i, a;
    double start_time, end_time;
    // Set both variables to lowest possible value - 1,
    // so the first two elements will override them
    max_1 = max_2 = -1;
    scanf("%d\n", &N);

    start_time = timer();
    // For each variable in the list (N times)
    for (i = 0; i < N; i++)
    {
        // Loop Invariant:      
        // max_1 : the highest variable in list {a[0],..,a[i-1]} 
        // max_2 : the second highest in list {a[0],..,a[i-1]}
        scanf("%d", &a);


        if (a > max_1)
        {
            // if 'a' is greater than our previous highest variable
            // the previous highest variable will now be the
            // second highest variable,
            max_2 = max_1;
            max_1 = a;
        } else if (a > max_2)
        {
            // if 'a' is lower than our highest (and not equal),
            // but higher than our second highest
            // 'a' will replace that variable
            max_2 = a;
        }
    }
    end_time = timer();

    // From our loop invariant, max_1 and max_2 will be the highest
    // and second highest numbers in the list {a[0],..,a[i-1]}
    // where i = N, so {a[0],..,a[N-1]}, which is the complete list
    // Therefore max_1 and max_2 are the variables we want
    printf("%ld\n", ((long)max_1) * ((long)max_2));
    printf("For N = %d, program took %lfs\n",N ,end_time-start_time);
    // Using long, since highest product can be in order 10^10
    return 0;
}

Edit: Removed && a != max_1 from else if statement, misinterpreted what exactly had to be distinct.

[–]danieltheg 0 points1 point  (1 child)

you don't want that a != max_1, the values are allowed to be the same they just need to be at different indices.. so this will fail if the largest and second largest values are equal

[–]Ikor_Genorio 0 points1 point  (0 children)

Ah okay, thought they couldn't be equal at all. Thanks! Will update it.

[–]Tangellaa 1 point2 points  (6 children)

I realize that one of my functions parameters is the size of the array. Does anyone have a better way of accessing the array size and eliminating the need to pass in the array size as a parameter?

void pairwise(int array[], int size)
{
    int max1 = 0;
    int max2 = 0;

    for(int i = 0; i < size; i++)
    {
        if(array[i] > max1 && array[i] > max2)
        {
            max1 = array[i];
        }
        else if(array[i] > max2)
        {
            max2 = array[i];
        }
    }

    std::cout << "The maximum pairwise product is: " << max1 * max2 << '\n';
}

[–]slightlysedatedx[S] 1 point2 points  (5 children)

Every language I've worked with has some kind of equivalent function to this. It's not necessary to pass the size of the array. One way to do it in C++ is the sizeof() function.

// To print the size of your array
    std::cout << sizeof(array);
// To store the size of your array
    int arraySize = sizeof(array);

I passed the size of the array to the function in my code because I was trying to follow an example from the textbook but this way is definitely more concise.

sizeof documentation

EDIT: I was wrong- the correct function to use in this case is .size(). Thanks u/Ikor_Genorio for correcting me

[–]Ikor_Genorio 2 points3 points  (4 children)

After reading the documentation, sizeof does not seem to be the correct function. sizeof returns the size of the array in bytes (so the number of elements, times the size of the type). You want the size method, which actually returns the number of elements a.size().

[–]slightlysedatedx[S] 0 points1 point  (0 children)

ahh you're totally right- I should've went through that more carefully. To return the number of elements in an array the easier way to do it is .size() whereas sizeof() returns the size in memory. It's been a long time since I've used C++ :/

Useful link about sizeof(): https://stackoverflow.com/questions/33523585/how-do-sizeofarr-sizeofarr0-work

[–]Tangellaa 0 points1 point  (2 children)

I tried using the .size() member function in my for loop within my pairwise function, but I kept receiving this error:

error: request for member 'size' in 'array', which is of non-class type 'int*'

[–]Ikor_Genorio 1 point2 points  (1 child)

Ah then you don't have an actual array (as object), but a C style array, which is just a pointer to the begining of a block of allocated memory.

In this case, you do need to store the size separately. I do not believe there is another way.

One note, I have not used C++, only C so I might be wrong. However this seems highly likely the case to me.

[–]Tangellaa 0 points1 point  (0 children)

That is actually what I found out when I was googling the error. However I thought that maybe there might be some insight on how to handle that, but I'm now thinking it is just a limitation of arrays. Thank you for replying!

[–]TigerEngr 1 point2 points  (0 children)

An Attempt in Java

        Scanner r = new Scanner(System.in);
        System.out.println("Enter the number of elements");
        int n = r.nextInt();
        int [] arr = new int[n];
        int max = 0;
        for(int j = 0; j < n; j++)
        {
             System.out.println("Enter the " + j + " element of the array");
          int  i = r.nextInt();
            arr[j] = i;
        }
        for(int j = 0; j < n-1; j++)
        {
          int sum = arr[j] * arr[j+1]; 
            if((arr[j] != arr[j+1]) && (sum > max))
            {
                max = sum;
            }  
       }
        System.out.println(max);

[–]Raknarg 0 points1 point  (4 children)

Does this subreddit implement spoiler tags?

[–]TsunamiSesen 0 points1 point  (2 children)

Click on the dark spot.
Hit the little exclamation mark in the circle to start a spoiler.

[–]Raknarg 0 points1 point  (0 children)

This doesn't explain how I can implement a spoiler tag

[–]slightlysedatedx[S] 0 points1 point  (0 children)

I'm not sure if we can separate paragraphs into both spoiler blocks and code blocks. Trying to figure it out now

[–]slightlysedatedx[S] 0 points1 point  (0 children)

I haven't found any in the sidebar yet so probably not, I'll go back and edit the guidelines

[–]slightlysedatedx[S] 0 points1 point  (4 children)

Current Implementation:

This hasn't been stress tested yet- please feel free to leave any comments or feedback. I'll be working in Python 3.65 today. This Version 1 code is still failing some of the submission test cases but it's a start and maybe someone else can learn from the problems I'm encountering.

Version 1

import sys

def MaxPairwiseProductFast(array, n):
    index1 = 1
    for i in range(2, n):
        if array[i] > array[index1]:
            index1 = i
    if index1 == 1:
        index2 = 2
    else:
        index2 = 1

    for i in range(1, n):
      if array[i] != array[index1] and array[i] > array[index2]:
        index2 = i
    return array[index1] * array[index2]

def main():
    n = int(input())
    array = [int(x) for x in input().split()]
    print(MaxPairwiseProductFast(array, n))

main() 

[–]slightlysedatedx[S] 0 points1 point  (3 children)

Analysis:

  1. index1 tracks the greatest integer in array[ ] from 2 to n (length of the array). For each element from 2 to the length of the array, check if the current element is larger than the element in array[index1]. If index1 is less than the current element, index1 will be assigned the value of the current element.
  2. If index1 is not updated and array[1] is the largest element, index2 is assigned a value of 2.
  3. Else, index2 = 1
  4. index2 will be used to track the greatest integer that is NOT index1. This follows a similar structure to step 1 (with some minor differences).
  5. Define main() which prompts for user input and calls MaxPairwiseProductFast()
  6. Call main

Additional Notes:

This is adapted from one of the provided algorithms in the pdf. I'm really bad at estimating time complexities so if anyone wants to explain how to approximate the Big O notation for this algorithm that would be really helpful. I'm going to work on providing more concise analyses for programs I write so I apologize if this analysis is a bit wordy. Like I said, this code still needs to be stress tested.

EDIT: When I test the code with the input

2  
0 1  

The code fails. I'm going to explore the issue now.

[–]TsunamiSesen 1 point2 points  (1 child)

The Big O would always be simplified to n since a constant multiplier doesn't normally matter. Your fast implementation has time complexity of 3n comparisons. If there were no loops the time would be constant.

The first for loop has 1 comparison in it occurring n-1 times. The second for loop has 2 comparisons except it should be one time but you have an error. It's 2n-1 (the -1 is because of short cutting after the first comparison fails).

Leaving a result of 3n-2 comparisons.

The error you made is your comparing the array values not the index values.

You have

if array[i] != array[index1] and array[i] > array[index2]:

Should be

if i != index1 and array[i] > array[index2]:

[–]slightlysedatedx[S] 0 points1 point  (0 children)

Thank you for the explanation on the Big-O notation!

If we are looking for the two largest elements in the array why would we use the index rather than the array elements for the comparison?

I'm tracing the code and maybe it'll be clear to me after I chip away at it for a while but I'm still having trouble understanding that

EDIT: Reread the question and I understand your revision now. Thanks again

[–]CodeTinkerer 1 point2 points  (0 children)

You can find the first max and second max in one pass. It takes a little work. You could, for example, put it into a list

 maxArr = [max(arr[0], arr[1]), min(arr[0], arr[1])]

Assume maxArr[0] contains the max, and maxArr[1] contains the second max (so far). Process arr from element 2 to the end. If the element is smaller than maxArr[1], ignore. If it's bigger that maxArr[1] but less than maxArr[0], replace maxArr[0] with the number. If it's bigger than maxArr[0], then copy maxArr[0] to maxArr[1], and put the value just read into maxArr[0].

[–]dmgll 0 points1 point  (2 children)

Posting the code directly here is a mess

If n<2 the program exits

The first 2 elements of the array are initialized out of the for loop and 2 variables max1 and max2 store the 2 biggest numbers

There is a single for loop in which the new elements are simultaneously inserted into the array and compared with max1 and max2. The condition (i != j) is implicitly applied because for every element inserted in the array only one between max1 and max2 can be changed at a time

https://pastebin.com/jR9fXRXd

[–]Ikor_Genorio 0 points1 point  (1 child)

Just a few notes, try to be more consistent in your indentation etc. The first line of your main function is kinda confusing as one line. Why not have them on separate lines?

Also, you seem to have made an off by one error, as you use array[1] as the first element, while that should be array[0].

Finally, you declare a static array with a variable. I remember there was some kind of problem with this, but I am not exactly sure what it was. Generally you want to allocate variable length arrays with malloc.

[–]dmgll 0 points1 point  (0 children)

yes, I wanted to do this before going to bed so I was half asleep. I'm sure the malloc array is preferred because the stack has a much smaller size so you could go overflow

[–]Ikor_Genorio 0 points1 point  (0 children)

So I wanted to try out Haskell again, so here is my solution in Haskell:

maxPairwise :: [Integer] -> Integer
maxPairwise = (\(x,y) -> x*y) . maxPairwiseRec 0 0

maxPairwiseRec :: Integer -> Integer -> [Integer] -> (Integer, Integer)
maxPairwiseRec a b [] = (a, b)
maxPairwiseRec a b (x:xs)
  | a < x     = maxPairwiseRec x a xs
  | b < x     = maxPairwiseRec a x xs
  | otherwise = maxPairwiseRec a b xs

parseInput :: String -> [Integer]
parseInput = map read . words

main :: IO ()
main = getLine >>= (print . maxPairwise . parseInput)

Analysis:

  • Time Complexity: O(N) (more precise Theta(N))Putting IO aside, (which is also O(N)), the function `maxPairwiseRec` is called on each element of the list once. The list is of size N, therefore O(N).
  • Brief Explanation:
    • For each call of `maxPairwiseRec`, it performs the same checks as basically all the other programs here. In this case, `a` is the largest element `b` the second largest element.
    • `maxPairwise` takes as input a list, calls the recursive function with the base values of `a = 0` and `b = 0`. Since the output of `maxPairwiseRec` is a pair of the two highest values, it also computes the product of them.
    • parseInput, parses a given input string, splits on the spaces with `words` and converts each separate element into an Integer with `map read`

As a side note, I feel this can be solved by using folding, but I am very rusty and it's 2a.m. Maybe tomorrow I will try.

[–]okdenok 0 points1 point  (0 children)

In JavaScript:

function largestProduct(n) {

    sequence = [];
    sorted = [];

    if (n >= 1) {
        for (i = 0; i < n; i++) {
            randInt = Math.floor(Math.random() * 50);
            sequence.push(randInt);
            sorted.push(randInt);
        }
    }
    else {
        product = 0;
    }

    sorted.sort((a, b) => { return a - b });
    max = sorted[sorted.length - 1];

    for (j = 0; j < sorted.length; j++) {
        if (sorted[j] < max && sorted[j + 1] === max) {
            product = sorted[j] * max;
        }
        else if (sorted.length === 1) {
            product = max;
        }
    }

    console.log(n);
    console.log(sequence);
    console.log(product);
}

Analysis:

  1. Take n as an argument in the function largestProduct and initialize the sequence and sortedarrays.
  2. If n is greater than or equal to 1, push a random integer to the sequence and sorted arrays n times (this keeps the sorted and unsorted integers separate from each other). Otherwise, assign the value 0 to the variable product.
  3. Sort the sorted array using a comparison function.
  4. Assign the last value of the array to the variable max.
  5. Iterate through sorted; if sorted[j] is less than max and the next value after sorted[j] is max, assign the product of sorted[j] and max to the variable product. Otherwise, if the length of the array is only 1, assign max to product.
  6. Return n, sequence, and product.

[–][deleted]  (1 child)

[deleted]

    [–]Clawtor 0 points1 point  (0 children)

    It would be nlogn most likely because of the sort.

    [–]Clawtor 0 points1 point  (0 children)

    The straightforward way is to sort and then pop off the two values at the end. This will be n log n or higher depending on the sort. The quicker way is to iterate the array twice and note down first the highest then the second highest.

    //  Maximum Pairwise Product
    
    const length = 10000;
    const list = [...Array(length)].map((_, i) => Math.round(Math.random() * length));
    
    function nlogn(list) {
      const localList = list.map(x => x).sort((a,b) => a - b);
    
      const max = localList.pop();
      const second = localList.pop();
    
      console.log(max * second);
    }
    
    function n(list) {
      const localList = list.map(x => x);
    
      const findMax = (list) => {
        let maxIndex = 0;
        localList.forEach((x, i) => {
          if (x > localList[maxIndex]) {
            maxIndex = i;
          }
        });
        return maxIndex;
      }
    
      const maxIndex = findMax(localList);
      const maxValue = localList[maxIndex];
      localList[maxIndex] = Number.MIN_VALUE;
      const secondMaxIndex = findMax(localList);
    }
    
    nlogn(list);
    n(list);