【问题标题】:Get largest value from array without sorting从数组中获取最大值而不进行排序
【发布时间】:2011-09-29 02:43:32
【问题描述】:

我正在创建一个有点简单的游戏,我需要跟踪哪些玩家的得分。 25人同时玩这个游戏,这些玩家将被放入一个数组中:

public static int[] allPlayers = new int[25];

比方说,根据正确答案,当前玩家将获得 100 分。因此,如果玩家 1 起床,代码将类似于以下内容:

allPlayers[0] += 100;

如果玩家 3 起床,则正确答案的代码为:

allPlayers[2] += 100;

在游戏结束时,我想确定哪个玩家的积分最多。请注意,我不能简单地对该数组进行排序,因为我需要数组的顺序保持不变。如果订单没有完好无损,我将无法分辨哪个玩家有哪个指向他/她的名字。

我很想听听大家的意见,期待您的回复。

非常感谢,

埃文

【问题讨论】:

    标签: c# winforms arrays


    【解决方案1】:

    无需排序,只需遍历数组,跟踪目前看到的最大值和该值的索引。

      var largest = -1;
      var player = -1;
      for (var i = 0; i < allPlayers.Length; ++i)
      {
           if (allPlayers[i] > largest)
           {
               player = i;
               largest = allPlayers[i];
           }
      }
    
      Console.WriteLine( "Player {0} wins, with score {1}", player, largest );
    

    处理关系留作练习。

    【讨论】:

    • 我真的很喜欢这种方法!谢谢你。
    【解决方案2】:

    如果您想要一个可能不止一个玩家的排名,则可以使用 Linq 作为替代方案(保持获胜玩家索引的简单循环对于基本情况更有效):

    var player = allPlayers.Select((x, i) => new { Score = x, Player = i })
                           .OrderByDescending(x => x.Score)
                           .First();
    
    Console.WriteLine("Player {0} wins with a score of {1}", player.Player, player.Score);
    

    【讨论】:

    • 这是否按照 OrderByDescending 建议的方式对数组进行排序?
    • @Evan: 不,数组本身保持不变,排序是在单独的枚举上完成的
    • 我知道我是一个绝对的痛苦,我已经阅读了一些关于这件事的书,但如果你或者看到此评论的其他人能够准确地解释这个问题的目的,我将不胜感激lambda 运算符是在这种情况下吗?我很想学习如何使用这个家伙!
    • @Evan:你可以把它理解为“去”——它基本上是一个匿名函数,它接受左侧的输入并将其映射到右侧的输出。另见msdn.microsoft.com/en-us/library/bb397687.aspx
    • 一个lamba“函数”是(在这个特定实例中)一个速记委托。
    【解决方案3】:

    我想成为一个 LINQ 纯粹主义者,并说如果您使用 OrderByDescending,那么您正在执行 O(NlogN) 排序。由于 max 是一个 O(N) 算法,我们应该能够使用 LINQ 做得更好。这是我对 LINQ 的 O(N) 建议:

      var player=allPlayers.Select((x, i) => new {Score=x, Player=i})
        .Aggregate((self, next) => self.Score>=next.Score ? self : next);
    
      Console.WriteLine("Player {0} wins with a score of {1}", player.Player, player.Score);
    

    【讨论】:

      【解决方案4】:

      使用

      int max = maxplayers.Max()//linq extension method of [] int
      

      this post

      【讨论】:

        【解决方案5】:

        如果您无法排序或保留可以进行排序的并行数据结构或保留对最大值的引用,那么您将拥有一个 O(n) 算法。

        最简单的方法是保留对插入到数组中的最大值的引用。

        【讨论】:

          【解决方案6】:

          使用 Linq:

          int max = allPlayers
               .Select((x, i) = > new { Player = i, Score = x })
               .OrderByDescending(x => x.Score)
               .First();
          

          没有 Linq:

          int score;
          int player;
          
          for(var i = 0; i < allPlayers.Length; i++)
          {
              if(allPlayers[i] > score)
              {
                  score = allPlayers[i];
                  player = i;
              }
          }
          

          【讨论】:

            【解决方案7】:

            您可以在整个过程中跟踪哪个玩家的最大值,在每次增加时您都可以查看新值是否大于旧值,这样您就可以知道哪个玩家具有最大值在比赛的任何时刻。

            private int maxPlayer = 0;
            private int value = 0;
            
            public void setIncrement(int player, int amount)
            {
                allPlayer[player] += amount; 
                if(allPlayer[player] > value) 
                { 
                    maxPlayer = player; 
                    value =  allPlayer[player];
                }
            }
            
            public int getMaxPlayer()
            {
            return maxPlayer;
            }
            

            【讨论】:

              【解决方案8】:

              只需按照其他人的建议迭代一次即可。这是不可避免的,

              除非

              您将您的玩家数组包装成一个数组并封装设置玩家分数的方式。然后,您可以在将内容添加到列表时进行比较。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2017-08-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-03-01
                相关资源
                最近更新 更多