N位数中M位的最大值

时间:2016-05-20 16:45:26

标签: c++

我正在尝试编写一个可以执行以下操作的程序:

in:
 5 4
 1 9 9 9 0

out:
9990

我有一个问题。它不适用于任何数字集。例如,它适用于上面的那个,但它不适用于这个:

in:
15 9
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4


out: 988887814

2 9 3 6 5 8 8 8 8 7 2 2 8 1 4

我用矢量方法做了这个,它适用于任何一组数字,但我试图将它做成一个堆栈以获得更好的复杂性。

编辑----为STD :: STACK修改 使用堆栈的方法代码:

#include <iostream>
#include <fstream>
#include <stack>
using namespace std;

ifstream in("trompeta.in");
ofstream out("trompeta.out");

void reverseStack(stack<char> st) {
    if(!st.empty())
    {
        char x = st.top();
        st.pop();
        reverseStack(st);
        out<<x;
    }
    return;
}
int main()
{
    int n,m,count=1;
    stack <char> st;
    char x;
    in>>n>>m;
    in>>x;
    st.push(x);

     for(int i=1; i<n; i++)
        {
            in>>x;
            if(st.top()<x && count+n-i-1>=m)
            {
              st.pop();
              st.push(x);
            }
            else
            {
                st.push(x);
                count++;
                if (count>m-1) break;
            }
        };

    reverseStack(st);
}

使用向量的方法代码:

#include <iostream>
#include <fstream>

using namespace std;
ifstream in ( "trompeta.in" );
ofstream out ( "trompeta.out" );
int main ()
{
    int i = 0, N, M, max, j, p = 0, var;
    in >> N >> M;
    char* v = new char[N];
    char* a = new char[M];
    in >> v;
    var = M;
    max = v[0];
    for ( i = 0; i < M; i++ )
    {
        for ( j = p ; j < N-var+1; j++ )
        {
            if ( v[j] > max  )
            {
                max = v[j];
                p = j;
            }
        }
        var--;
        a[i] = max;
        max = v[p+1];
        p = p+1;
    }
    for ( i = 0; i < M; i++ )
        out << a[i]-'0';
}

any1可以帮助我让STACK代码正常工作吗?

3 个答案:

答案 0 :(得分:1)

使用这一事实,即最重要的数字完全胜过除了平局之外的所有其他数据,我会查看第一个(N-M + 1)个数字,找到该范围内的最大单个数字。

如果它出现一次,则锁定第一个数字。丢弃在该位置之前出现的数字,并重复“N-position的M-1个数字的最大值”以查找该数字的剩余数字。回答。 (或N位置-1,如果位置为零)

如果它多次出现,则递归地找到每个“N位置的M-1个数的最大值”,然后从这些中选择最大的单个结果。最多可以有N个这样的比赛。

我忘了提及,如果N == M,你也完成了。

递归证明: 计算子匹配的值将始终选择M-1个数字。当M为1时,您只需要选择几个位置中的最大位置,并且不再有递归。这两种情况都是如此。此外,“选择”步骤始终包含不超过N个选项,因为它们始终基于选择一个最高有效数字。

------------------你怎么用堆栈来做----------------

使用堆栈的实际实现将基于包含问题的整个状态的对象,在每个步骤中,如下所示:

struct data { // require: n == digits.size()
    int n, m;
    std::string digits;
    bool operator<(const data &rhs){ return digits < rhs.digits; }
};

这一点不仅仅是存储原始问题,而是要有一种方法来表示任何子问题,你可以在堆栈上推送和弹出。在这里,堆栈本身并不重要,因为它用于在特定层中选择一个最佳结果。递归处理大部分工作。

这是隐藏数据结构的顶级函数:

std::string select_ordered_max(int n, int m, std::string digits) {
    if (n < m || (int)digits.size() != n)
        return "size wrong";
    data d{ n, m, digits };
    data answer = select_ordered_max(d);
    return answer.digits;
}

和递归主力的粗略伪代码

data select_ordered_max(data original){
    // check trivial return conditions
    // determine char most_significant
    // push all subproblems that satisfy most_significant 
        //(special case where m==1)
    // pop subproblems, remembering best
    return answer {original.m, original.m, std::string(1, most_significant) + best_submatch.digits };

}

当您只比较完全相同长度的字符串时,字符串比较适用于数字。这就是这种情况。

是的,我知道n和m在digits.size()中是多余的,但我不想太努力。包括它两次简化了一些递归检查。如果候选者通过该递归级别的最大数字检查,则实际实现仅将候选者推送到堆栈。这使我能够从输入的15位数中得到正确的9位数答案,只有28位候选者被推入堆栈(并且在最大选择期间弹出它们)。

答案 1 :(得分:0)

- 编辑 -

这是基于我之前使用vector

的建议的STACK建议
findMaxValueOutOfNDigits(stackInput, M, N)
{
  // stackInput = [2, 9, 3, 6, 5, 8, 8, 8, 8, 7, 2, 2, 8, 1, 4]
  // *where 4 was the first element to be inserted and 2 was the last to be inserted
  // if the sequence is inverted, you can quickly fix it by doing a "for x = 0; x < stack.length; x++ { newStack.push(stack.pop()) }"

  currentMaxValue = 0

  for i = 0; i < (M - N + 1); i++
  {
    tempValue = process(stackInput, M, N)
    stackInput.pop()
    if (tempValue > currentMaxValue)
      currentMaxValue = tempValue
  }

  return currentMaxValue
}

process(stackInput, M, N)
{
  tempValue = stackInput.pop() * 10^(N - 1)
  *howManyItemsCanILook = (M - N + 1)

  for y = (N - 2); y == 0; y++
  {
    currentHowManyItemsCanILook = *howManyItemsCanILook

    tempValue = tempValue + getValue(stackInput, *howManyItemsCanILook) * 10^(y)

    *howManyItemsCanILook = *howManyItemsCanILook - 1

    for x = 0; x < (currentHowManyItemsCanILook - *howManyItemsCanILook); x++
    {
      stackInput.pop()
    }
  }

  return tempValue
}

getValue(stackInput, *howManyItemsCanILook)
{
  currentMaxValue = stackInput.pop()
  if (currentMaxValue == 9)
    return 9
  else
  {
    goUntil = *howManyItemsCanILook

    for i = 0; i < goUntil; i++
    {
      *howManyItemsCanILook = *howManyItemsCanILook - 1
      tempValue = stackInput.pop()
      if (currentMaxValue < tempValue)
      {
        currentMaxValue = tempValue
           if (currentMaxValue == 9)
                return currentMaxValue
      }
    }
    return currentMaxValue
  }

}

注意:其中* howManyItemsCanILook通过引用传递

我希望这会有所帮助

答案 2 :(得分:0)

现在你的代码有很多问题,但不是专注于那些让我们回答这个问题。假设您的代码已更正为我们提供:

  • const size_t M其中M是输出中预期的位数
  • const vector<int> v这是大小为N
  • 的输入数字集

您总是希望选择剩余最高值的最高值。因此,我们将保留一个end迭代器,以防止我们选择一个不会给我们留下足够数字来完成数字的数字,并使用max_element选择:

const int pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
auto maximum = 0;
auto end = prev(cend(v), M - 1);
auto it = max_element(cbegin(v), end);

for (auto i = M - 1; i > 0; --i) {
    maximum += *it * pow10[i];
    advance(end, 1);
    it = max_element(next(it), end);
}
maximum += *it;

Live Example

此代码取决于M大于0且小于N且小于log10(numeric_limits<int>::max())

编辑:不幸的是这解决了连续的数字问题,修改后的问题,希望以后的数字,但不一定是连续的

因此,鲜为人知的numeric库提供了inner_product,这似乎只是这项工作的工具。现在你的代码有很多问题,但不是专注于那些让我们回答问题。假设您的代码已更正为我们提供:

  • vector<int> foo(M)其中M是输出中预期的位数
  • const vector<int> v这是大小为N
  • 的输入数字集

我们会在foo中使用inner_product,以10的递减次数初始化它:

generate(begin(foo), end(foo), [i=int{1}]() mutable {
    auto result = i;
    i *= 10;
    return result; });

然后我们可以在循环中使用它:

auto maximum = 0;

for (auto it = prev(rend(v), size(foo) + 1); it != rbegin(v); advance(it, -1)) {
    maximum = max<int>(inner_product(cbegin(foo), cend(foo), it, 0), maximum);
}
maximum = max<int>(inner_product(cbegin(foo), cend(foo), rbegin(v), 0), maximum);

Live Example

要使用it初始化,要求您的初始M小于N,因此您可能希望assert或{{1}}一些东西。