-1

I am a beginner in Qt, in the below code, I found out the maximum number, but I need to find the second maximum number, too.

int max;
max = List.at(0).toInt();

for(int i=1; i<List.size(); i++)
{
    if(List.at(i).toInt()>max)
        max = List.at(i).toInt();
    if(List.at(i).toInt()<max)
        max = List.at(0).toInt();
}

qDebug()<<"max val:"<< QString::number(max);
ui->textEdit->setText(QString::number(max));
László Papp
  • 51,870
  • 39
  • 111
  • 135

3 Answers3

2

The easiest way is to drop your concept and just use this;

QList<int> intList;
foreach (const QString &myString, list)
    intList.append(myString.toInt());

qSort(intList.begin(), intList.end(), qGreater<int>());
qDebug() << "MAX:" << intList.first();
qDebug() << "SECOND MAX:" << intList.at(1);

It is a bit slower than your original concept, O(n*log(n)) average and O(n^2) worst case complexity with something like quick sort. Other sorts like merge sort and so on might be even slower.

However, it most of the time does not matter when using Qt since the Qt containers are inherently slower than their standard library counterparts, so I will take that this is not a main issue. If it is, you may consider switching to the standard library and use your concept which I will fix below.

Basically, you would be using qSort to sort your content in ascending order. Note that I should the first() convenience method to get the first item as opposed to your original try of at(0). It is basically the same, but more self-explanatory.

If you need to keep the original containers as is, you can just make a copy of it.

If you really want to stick with your original concept, I would write this:

main.cpp

#include <QDebug>
#include <QStringList>

int main()
{
    QStringList List{"10", "7", "2"};
    int max, secondMax;
    secondMax = max = INT_MIN;

    foreach (const QString &string, List) {
        int i = string.toInt();
        if (i > max) {
            secondMax = max;
            max = i;
        } else if (i > secondMax) {
            secondMax = i;
        }
    }

    if (secondMax == INT_MIN)
        secondMax = max;

    qDebug() << "max val:" << max;
    qDebug() << "second max val:" << secondMax;

    return 0;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
CONFIG += c++11

Build and Run

qmake && make && ./main

Output

max val: 10 
second max val: 7

Note that it is better to use Qt's foreach as opposed to the C style iteration as you do not need the index after all. That being said, it is untested code, but the concept is valid, so take it pseudo-code which you may need to adjust to your need.

It is not completely your original concept either, but I think I would do it this way.

László Papp
  • 51,870
  • 39
  • 111
  • 135
  • Ascending -> Descending order in the explanation. – László Papp May 17 '14 at 05:44
  • Unless you add a demotion of `max` to `secondMax` when `max` is replaced by a larger value, this (the second sample) won't always work. And for only two values the second sample is *far* superior to the first once that problem is addressed. 2*O(N) will beat the hell out of O(NlogN) unless N is trivially small. – WhozCraig May 17 '14 at 05:49
  • @WhozCraig: what do you mean? The only issue I could come up with is unstable container with two max items, but it depends on what the OP wanted to get in that corner case, hence the "the concept is valid, so take it pseudo-code which you may need to adjust to your need.". Not sure if you are referring to that. – László Papp May 17 '14 at 05:50
  • I mean suppose your sequence was 2 5 7. When finished your second algorithm will result in `max = 7` and `secondMax = 2`. A replacement of `max` should demote the *current* `max` as the new `secondMax` – WhozCraig May 17 '14 at 05:52
  • `And for only two values the second sample is far superior to the first once that problem is addressed.` -> That may or may not be premature optimization, and most definitely, the former is "far superior" for maintenance. In fact, if you work on performance critical code, you would not use Qt and especially Qt containers. Your concern is fixed, thanks! The stable concern of mine is still there, but it depends on what the OP exactly wants in that regard. – László Papp May 17 '14 at 05:53
  • @WhozCraig: also, O(2*n) would still be O(n) since 2 is a constant, but it is just one iteration anyhow. – László Papp May 17 '14 at 06:01
  • Sure. If performance were a mandate I wouldn't use qSort (or qsort, or std::sort) *at all* to do this specific task. I would use your second algorithm and call it good. For a kth-top-element general solution I would use quick select, but that is *way* overkill for this specific need. And the 2 was specifically to demonstrate the worst-case comparision-count scenario, a sequence of largest, then smallest to second largest, i.e. 10, 1,2,3,4,5,6,7,8,9 would result in 20 comparisons. In the end 2*O(N) is still O(N), obviously. The 2 is called out specifically because that is the top-N sought. – WhozCraig May 17 '14 at 06:05
  • And thanks for fixing the demotion problem. +1, btw. – WhozCraig May 17 '14 at 06:06
  • The second algorithm is still using qt containers, and they are inherently slow for API convenience, so you could gain some performance there by dropping them if it is really performance critical. :) – László Papp May 17 '14 at 06:06
  • I probably should have also brought up that the sequence I mentioned for worst-case will expose one more problem in your second algorithm. Both `max` and `secondMax` would initially be 10, and no other value in the sequence would replace *either*. I.e. if he largest value is the *first* value in your container, `secondMax` will never get a chance to hold the second largest. May want to address that as well. – WhozCraig May 17 '14 at 06:11
  • @WhozCraig: fixed, I actually even wrote some demo code that can be run and checked. – László Papp May 17 '14 at 06:25
  • @WhozCraig: I think I need a special check for list.size == 1, because in that case secondMax will remain INT_MIN as opposed to first(), but other than that, it is good, I think? – László Papp May 17 '14 at 06:43
  • I like how you have it now, If desired, set `secondMax = max;` *after* the loop if `secondMax == INT_MIN`. gj btw. – WhozCraig May 17 '14 at 15:10
1

Try with my code:

   int max,second_Max=0;
   max = List.at(0).toInt();
   for( int i=1; i<List.size(); i++)
       {
        if(List.at(i).toInt()>max && second_Max!=2) {
            max = List.at(i).toInt();
            second_Max++;
        }
    }
0

Why don't you just sort from ascending to descending and then use the indices to get the maximum and second max?

      int i, j;
      int temp;             
      int size = List.size(); 
      for(i = 1; i <= size; i++)
     {
          for (j=0; j < (size - 1); j++)
         {
               if (List.at(j+1).toInt() > List.at(j).toInt())     
              { 
                    temp = List.at(j).toInt();            
                    List.at(j).toInt() = List.at(j+1).toInt();
                    List.at(j+1).toInt() = temp;
               }
          }
     }
Quaxton Hale
  • 2,460
  • 5
  • 40
  • 71