【问题标题】:How to build a function that evaluates an integer as a LIFO collection in C#如何在 C# 中构建一个将整数计算为 LIFO 集合的函数
【发布时间】:2020-11-23 11:52:34
【问题描述】:

问题是: 编写一个函数(AllExist),它接收一个非空堆栈stk(int)作为参数,如果堆栈中每个数字的所有第一个数字都作为stk的任何数字的最后一个数字出现,它将返回true , 否则返回 false。 例如: 对于stk(从顶部向下开始)122、251、565、12334、28、7。该函数将返回true。 1 、 2 、 5 和 7 出现在堆栈中任何数字的最后一位。

** clone 是一个函数,它返回与给定堆栈相同的堆栈。

我的建议:

public static bool AllExist(stack<int> stk)
{
  int x=0; int i; int z; bool bl; string str;
  stack <int> stk1=clone (stk);
  while (!stk1.IsEmpty())
  {
    i=stk1.Pop();
    while(i>=10)
    i/=10;
    x=x*10+i;
  }
 str=x.ToString();
 stack<int> stk2=Clone(stk);
 while(!stk2.IsEmpty())
 {
   z=stk2.Pop()%10;
   if (str.IndexOf(z.ToString())>-1)
     bl=true;
   bl=false;
 }
return bl;
}

** 这都是翻译,如有误解,敬请原谅。

谢谢!

【问题讨论】:

  • 如果您实际上是在对集合进行迭代,那么任何理由让它成为一个堆栈。
  • 我认为实现不正确。显然x 被一遍又一遍地覆盖,直到堆栈为空;这可能不是你想要的。在上层while 循环终止时,x 仅取决于堆栈底部。第二个whileloop 的行为方式类似。

标签: c# stack


【解决方案1】:

您可以使用 LINQ 解决此问题,例如:

static void Main(string[] args)
{
     Console.WriteLine(AllExist(new Stack<int>(new List<int>() { 122, 251, 565, 12334, 28, 7 })));
}

public static bool AllExist(Stack<int> stk) => stk.All(
     firstDigitItem => stk.Where(
          lastDigitItem => lastDigitItem.ToString().Last() == firstDigitItem.ToString().First())
     .Count() > 0);
   

它是如何工作的:

  • 如果集合中的所有项目都满足条件,则使用 stk.All() 将返回 true。
  • 然后我们从集合中选择一个项目 - firstDigitItem 并开始将此项目的第一个数字与集合中的每个其他最后一个数字项目进行比较。使用 .ToString().First() 或 .ToString().Last()
  • 如果超过 0 个元素满足我们的条件 - 我们会继续检查其他项目。
  • Else:“Where”返回 false,“All”自动返回 false。

甚至更优化的方式:

public static bool AllExist(Stack<int> stk) => stk.All(
     firstDigitItem => 
          stk.Any(lastDigitItem => lastDigitItem.ToString().Last() == firstDigitItem.ToString().First()));

在这里,使用“Any”,我们只寻找满足我们谓词的第一个元素,而不是“Where”的所有元素。

【讨论】:

    【解决方案2】:

    开始时,始终将您要解决的问题分解为较小的问题并解决这些问题。如果你分得够多,你真正要解决的问题实际上是一个很容易被验证为正确的衬线。

    你需要什么?首先是一种提取整数最后一位数字的方法。好的,这很简单,任何数字的最后一位都是除以10的余数:

    private static int ExtractLastDigit(this int i)
    {
        return i % 10;
    }
    

    我们还需要一种提取第一位数字的方法。最简单的方法是缩小数字,以便我们正在寻找的数字是唯一剩下的数字。我们可以使用 Log10 做到这一点:

    private static int ExtractFirstDigit(this int i)
    {
        var scale = (int)Math.Log10(i);
        return (int)(i / Math.Pow(10, scale));
    }
    

    现在,有很多方法可以做到这一点。最容易理解的是建立两个集合;一个包含所有第一个数字,另一个包含所有最后一个数字,检查前者中的所有项目是否都存在于后者中。因为您将在后者中刻苦地搜索,所以如果输入集合足够大,将最后一位数字存储在搜索有效的集合中通常是一个好主意。框架提供了这样的集合:HashSet&lt;T&gt;

    我将使用 linq,但使用经典循环构建集合相当简单。

    var firstItems = inputStack.Select(i => i.ExtractFirstDigit());
    var lastItems = new HashSet<int>(inputStack.Select(i => i.ExtractLastDigit()))
    

    现在,使用逻辑运算符All linq 提供:

    var validInput = firstItems.All(f => lastItems.Contains(f));
    

    大致翻译为:

    var validInput = true;
    
    foreach (var first in firstItems)
    {
        if (!lastItems.Contains(f))
        {
            validInput = false;
            break;
        }
    }
    

    你就完成了。

    有没有更有效的解决方案?当然可以,但你真的需要它们吗?如果答案是肯定的,请习惯于首先构建一个可行的解决方案,然后开始尝试使用可以衡量和测试的明确性能目标来优化它。如果您不这样做或它已经达到您的目标,那么您就有了一个易于理解和维护的有效解决方案。

    【讨论】:

    • 在声明lastItems时,大概你想输入inputStack.Select(i =&gt; i.ExtractLastDigit())
    猜你喜欢
    • 1970-01-01
    • 2010-09-23
    • 2022-01-09
    • 1970-01-01
    • 2014-02-06
    • 1970-01-01
    • 2016-01-31
    • 1970-01-01
    • 2016-07-06
    相关资源
    最近更新 更多