【问题标题】:count frequencies of all elements in array without using another array or changing the elements of the given array在不使用另一个数组或更改给定数组的元素的情况下计算数组中所有元素的频率
【发布时间】:2020-11-12 07:39:05
【问题描述】:

你好,所以这个问题的问题是你不应该使用另一个数组或函数,不要更改给定数组的元素或对它们进行排序,我们不知道元素的间隔 和旁注我不应该显示两次数字

例如,如果我们有 [10]={1,2,1,3,1,5,2,4,3,1} 它应该打印出来:

1 --- 4

2 --- 2

3 --- 2

4 --- 1

5 --- 1

我编写了一个代码,用于使用两个 for 循环查找重复数字,但我不知道如何阻止它重复相同的答案以及如何让它显示计数器

代码如下:

#include<iostream>
using namespace std;

int main()
{
    int arr[5];
    int size = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < 5; i++)
    {
        cout << "Enter " << i << " number:";
        cin >> arr[i];
    }
    {
        for (int i = 0; i < size; i++)
            for (int j = i + 1; j < size; j++)
                if (arr[i] == arr[j])
                    cout << " Repeating elements are " << arr[i] << " " << endl;
    }
    return 0;
}

【问题讨论】:

  • using namespace std; 是 C 中的语法错误:它不遵循语言规则。
  • 这看起来像是来自某个竞赛/挑战/竞争性编码/黑客网站。是吗?如果您的目标是学习 C++,那么您将不会在那里学到任何东西。在几乎所有情况下,就像这个一样,正确的解决方案是基于数学或编程技巧。如果您不知道诀窍是什么并尝试编写蛮力方法,则程序运行缓慢并因此失败。如果你想学习 C++,你不会从毫无意义的在线竞赛网站 but only from a good C++ textbook 学到任何东西。
  • 数组中存在的元素是否有任何范围?
  • 另外,为什么要int size = sizeof(arr) / sizeof(arr[0]);?你刚刚声明了一个大小为 5 的数组。所以我猜你已经知道它有多少个元素
  • 你可能不被允许使用它,但std::map 毫不费力地解决了这样的问题。 std::map&lt;int, int&gt; freqcount; 然后 freqcount[arr[i]]++; 计数。要打印频率,请使用 range-based for loop 进行迭代。

标签: c++ arrays loops for-loop while-loop


【解决方案1】:

逻辑:

正如您所说,不会有负数,我将重复值设为当前值的负数(以记住它是重复值),每当我遇到负值时,我都会将其设为正数(以获得回到原来的数组)。

#include <iostream>

int main()
{
    int arr[10] = {1,2,1,3,1,5,2,4,3,1}, cnt = 0, size = 10;

    for (int i = 0; i < size; i++) {
      cnt  = 1;

      if (arr[i] < 0) {
        arr[i] = -arr[i];
        continue;
      }

      for (int j = i + 1; j < size; j++) {

          if (arr[i] == arr[j]) {
            arr[j] = -arr[i];
            cnt++;
          }
        }

        std::cout <<  arr[i] << " " << cnt << '\n';
      }

    return 0;
}

输出:

1 4
2 2
3 2
5 1
4 1

注意:

如果允许更改数组中的值,请确保我们将在程序结束时保留原始数组。

【讨论】:

  • 添加一些关于您添加的内容的信息/已修复的内容会更好地让每个人都理解。
  • 这与无法修改数组的事实不兼容
  • rtoijala 的建议避免了这些问题,反正是的,OP 问题还不够清楚
【解决方案2】:

请看下面的代码。

为简洁起见,我将数组设为常量。您只需复制粘贴从用户输入读取的代码即可。

诀窍是检查每个i,这是第一次找到a[i]。如果之前已经找到,那么它已经算在上一次迭代中了,现在可以跳过。

#include <iostream>
using namespace std;

int main()
{
    const int a[]={1,2,1,3,1,5,2,4,3,1};
    const int size = sizeof(a) / sizeof(a[0]);

    for (int i = 0; i < size; i++)
    {
        bool duplicate = false;
        for (int j = 0; j < i; j++)
        {
            if (a[i] == a[j])
            {
                duplicate = true;
                break;
            }
        }
        if (duplicate)
        {
            continue;
        }
        int count = 1;
        for (int j = i + 1; j < size; j++)
        {
            if (a[i] == a[j])
            {
                count++;
            }
        }
        cout << a[i] << " -- " << count << '\n';
    }
}

【讨论】:

  • 有时候偷懒比较好,做const int a[]={1,2,1,3,1,5,2,4,3,1};否则为什么要const int size = sizeof(a) / sizeof(a[0]);,如果你知道大小是10?
  • @bruno 好点。硬编码的10 是从问题中复制粘贴示例数组留下的。删除它会好得多。
  • 如果你的编译器是最新的,你可以跳过sizeof tango 并使用std::size
【解决方案3】:

保持前一个最小的并在数组中寻找下一个最小的元素。然后运行一个循环对其进行计数并将先前的最小设置为当前的最小。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int N;
    cin >> N;
    vector<int> V(N);
    for (int& e : V)
        cin >> e;

    int prev_smallest = numeric_limits<int>::min();
    int smallest = numeric_limits<int>::max();
    for (int c = 0; c < N; )
    {
        for (int j = 0; j < V.size(); ++j)
            if (prev_smallest < V[j] && V[j] < smallest)
                smallest = V[j];

        int count = 0;
        for (int j = 0; j < V.size(); ++j)
            if (V[j] == smallest)
                ++count;
        cout << smallest << ' ' << count << endl;
        prev_smallest = smallest;
        smallest = numeric_limits<int>::max();
        c += count;
    }
}

【讨论】:

  • size_t j 而不是int j(2 次),当您给#include 时,请给所有这些,所以添加#include &lt;limits&gt;
  • 在 C++ for (auto v : V) if (prev_smallest &lt; v &amp;&amp; v &lt; smallest) smallest = v;for (auto v : V) if (v == smallest) ++count; 中,否则如果 C 用于数组迭代太多并且允许偷懒:)
  • 您的提议很有趣,但如果数组包含数组中使用的numeric_limits&lt;int&gt;::min(),则它不起作用(这不是问题,当然数字是正数),如果数组似乎有效包含numeric_limits&lt;int&gt;::max()
  • @bruno 可以轻松修复。运行一个单独的循环来检查数组中是否存在numeric_limits&lt;int&gt;::min()。如果确实如此,则对其进行计数并打印。然后运行上面的两个循环。 c 将来自 N- count of(numeric_limits&lt;int&gt;::min()
  • @bruno 是的,对此感到抱歉。我正忙着写信给另一位关于代码审查的评论者。当我解决这样的问题时,我已经习惯于看到这样的警告,如果有 0 个错误,我就会忽略它们。谢谢你的时间!我有很多东西要学。
【解决方案4】:

此例程对数组中的每个计数值进行一次遍历,以及一次初始遍历以确定要计数的最小值和最大值。此外,它以递增的顺序打印值。

for(;;) {} 技巧等同于while(true) {},即“永远迭代”。循环实际上不会永远工作,因为它会中断最后一个 if() 中的迭代。

void printCounts()
{
    const int a[]={1,2,1,3,1,5,2,4,3,1};
    const int size = sizeof a / sizeof a[0];

    int currentValue = a[0];
    int maxValue     = a[0];

    // find the first (minimum) and the last (maximum) value to count

    for (int i = 1; i < size; i++)
    {
        if (a[i] < currentValue)
            currentValue = a[i];
        if (a[i] > maxValue)
            maxValue = a[i];
    }

    // count items equal current value,
    // identify a next value to count,
    // print result,
    // reiterate
    for (;;)
    {
        int count = 0;
        int nextValue = maxValue;

        for (int i = 0; i < size; i++)
        {
            if (a[i] == currentValue)
                count ++;
            if (a[i] > currentValue && a[i] < nextValue)
                nextValue = a[i];
        }

        std::cout << "value:" << currentValue << "  count:" << count << std::endl;

        // all values counted ?
        if (currentValue == maxValue)
            break;

        // count nextValue
        currentValue = nextValue;
    }
}

通过GDB online Debugger 验证。结果是:

value:1  count:4
value:2  count:2
value:3  count:2
value:4  count:1
value:5  count:1

【讨论】:

    【解决方案5】:

    当然,如果允许您使用标准容器,例如std::map,您可以轻松完成任务。

    这是一个演示程序。

    #include <iostream>
    #include <map>
    
    int main() 
    {
        int a[] = { 1, 2, 1, 3, 1, 5, 2, 4, 3, 1 };
        std::map<int, size_t> m;
        
        for ( const auto &item : a )
        {
            ++m[item];
        }
    
        for ( const auto &item : m )
        {
            std::cout << item.first << " --- " << item.second << '\n';
        }
    
        return 0;
    }
    

    程序输出是

    1 --- 4
    2 --- 2
    3 --- 2
    4 --- 1
    5 --- 1
    

    如果您不允许使用任何标准容器并且不得以任何方式更改数组并且输出应根据存储在数组中的值进行排序那么您可以使用以下(虽然效率低)方法只使用循环。

    这是另一个演示程序。

    #include <iostream>
    
    int main() 
    {
        int a[] = { 1, 2, 1, 3, 1, 5, 2, 4, 3, 1 };
         
        const size_t N = sizeof( a ) / sizeof( *a );
         
        int value;
        
        for ( size_t n = 0; n != N; )
        {
            size_t i = 0;
            
            if ( n != 0 )
            {
                while ( ( i != N ) && !( value < a[i] ) ) ++i;
            }
    
            size_t count = 1;
            size_t min_i = i;
            
            while ( ++i != N )
            {
                if ( ( a[i] < a[min_i] ) && ( n == 0 || value < a[i] ) )
                {
                    min_i = i;
                    count = 1;
                }
                else if ( a[min_i] == a[i] )
                {
                    ++count;
                }
            }
    
            value = a[min_i];
            std::cout << value << " --- " << count << '\n';
            
            n += count;
        }
         
        return 0;
    } 
    

    程序输出同上图。

    1 --- 4
    2 --- 2
    3 --- 2
    4 --- 1
    5 --- 1
    

    【讨论】:

      猜你喜欢
      • 2021-07-28
      • 1970-01-01
      • 2020-07-10
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 2013-11-27
      • 2019-09-12
      • 1970-01-01
      相关资源
      最近更新 更多