C# 如何在C中构建将整数作为后进先出集合进行计算的函数

C# 如何在C中构建将整数作为后进先出集合进行计算的函数,c#,stack,C#,Stack,问题是: 编写一个函数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&g

问题是: 编写一个函数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;
}
**这一切都是我为任何误解感到抱歉


谢谢大家!

您可以使用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。如果集合中的所有项都满足条件,则返回true。 然后,我们从集合中选择一个项目-firstDigitItem,并开始将此项目的第一位数字与集合中的其他最后一位数字项目进行比较。使用.ToString.First或.ToString.Last 如果超过0个元素满足我们的条件-我们将继续检查其他项目。 Else:其中返回false,All自动返回false。 或者更优化的方式:

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

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

开始时,总是将您试图解决的问题分解为更小的问题并解决它们。如果你对它进行了足够的拆分,那么你真正需要解决的问题实际上是一行代码,可以很容易地验证它的正确性

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

我们还需要一种提取第一个数字的方法。最简单的方法是缩小数字的比例,这样我们要寻找的数字就是剩下的唯一数字。我们可以使用Log10实现这一点:

private static int ExtractFirstDigit(this int i)
{
    var scale = (int)Math.Log10(i);
    return (int)(i / Math.Pow(10, scale));
}
现在,有很多方法可以做到这一点。最容易理解的是构建两个集合;一个包含所有第一位数字,另一个包含所有最后一位数字,用于检查前一位中的所有项目是否都存在于后一位中。因为您将在后者中进行孜孜不倦的搜索,如果输入集合足够大,通常,将最后的数字存储在搜索效率高的集合中是一个好主意。框架提供了这样的集合:HashSet

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

var firstItems = inputStack.Select(i => i.ExtractFirstDigit());
var lastItems = new HashSet<int>(inputStack.Select(i => i.ExtractLastDigit()))
这大致可以转化为:

var validInput = true;

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


是否有更有效的解决方案?当然,但你真的需要吗?如果答案是肯定的,那就习惯于首先构建一个有效的解决方案,然后开始尝试通过明确的性能目标对其进行优化,您可以对其进行测量和测试。如果您没有或者它已经达到了您的目标,那么您就有了一个易于理解和维护的工作解决方案。

如果您实际迭代集合,是否有理由将其作为堆栈。我认为实现是不正确的。显然,x被一次又一次地覆盖,直到堆栈为空;这也许不是你想要的。在上部while循环终止时,x仅取决于堆栈的底部。第二个whileloop的行为与之类似。在声明lastItems时,您可能希望键入inputStack.Selecti=>i。ExtractLastDigit@trashr0x是的,修好了。谢谢
var validInput = firstItems.All(f => lastItems.Contains(f));
var validInput = true;

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