【问题标题】:Remove lowest integer from list using for loops使用 for 循环从列表中删除最小整数
【发布时间】:2017-04-21 12:02:30
【问题描述】:

我正在尝试编码挑战,但遇到了困难。 这个想法是在List<int> 中找到最小的整数,并返回一个新列表,删除该值但保留原始顺序。 我正在尝试仅使用 for 循环来做到这一点。

我遇到的问题是,当我迭代并将每个值与其他值进行比较时,我的最终结果只会出现一个数字小于另一个的最后一个实例,不一定是最小的数字。

例如,如果我传入List<int> { 1, 2, 3, 4, 5 },结果会返回为 4。

我意识到在重复的列表中使用 MinRemove(或类似名称)会更容易,但我故意让自己过得很艰难。

public static List<int> RemoveSmallest(List<int> numbers)
        {
            var newList = new List<int>();
            var lowest = 0;

            for (var i = 0; i <= numbers.Count - 1; i++)
            {
                for (var n = 0; n <= numbers.Count - 1; n++)
                {
                    if (numbers[i] < numbers[n])
                    {
                        lowest = numbers[i];
                    }
                }
            }

            foreach (var num in numbers)
            {
                if (num != lowest)
                {
                    newList.Add(num);
                }
            }

            newList.Remove(lowest);
            return newList;
        }

【问题讨论】:

  • 首先,你不需要嵌套循环。
  • 想扩展一下吗?

标签: c# list for-loop


【解决方案1】:

这是最接近您的代码,可以解决您的问题:

public static List<int> RemoveSmallest(List<int> numbers)
{
    var newList = new List<int>();

    if (numbers != null && numbers.Count > 0)
    {
        var lowest = numbers[0];

        for (var i = 1; i < numbers.Count; i++)
        {
            if (numbers[i] < lowest) {
                lowest = numbers[i];
            }
        }

        foreach (var num in numbers)
        {
            if (num != lowest)
            {
                newList.Add(num);
            }
        }
    }
    return newList;
}

编辑:由于在 cmets 中存在一些问题,我在代码中添加了一个检查列表是否为空。

【讨论】:

  • 如果您将问题中 OP 使用的列表作为示例输入传递,它将返回完全相同的列表,不会删除任何内容(没有一个数字小于 0)
  • @UnholySheep 是的,我修好了。
  • 如果列表为空会发生什么? List 在数组中没有成员会发生什么?这根本不是安全代码。
  • @alexc95 我个人认为解决特定问题的代码示例不需要在生产环境中进行所有可能的检查。但是你现在看起来更好吗?
  • @alexc95 即使在我的第一个未保存版本中,我也添加了警告。所以我没有得到这里的危险。
【解决方案2】:

这应该可以解决问题。

public static List<int> RemoveSmallest(List<int> numbers)
{
    if (numbers == null)
    {
        throw new ArgumentNullException("numbers");
    }

    if (numbers.Count > 1)
    {
        int smallest = numbers[0];
        int smallestIdx = 0;
        for (int i = 1; i < numbers.Count; ++i)
        {
            if (numbers[i] < smallest)
            {
                smallest = numbers[i];
                smallestIdx = i;
            }
        }
        return new List<int>(numbers.Where((value, index) => index != smallestIdx));
    }
    else
    {
        return new List<int>(0);
    }
}

请注意,numbers.Where() 基本上是对所有数字执行第二个 while 循环,因此复杂度为 2O(n),即 O(n)。

【讨论】:

    【解决方案3】:

    假设最低项不重复,则可以将最低项的索引存储在变量中。

    public static List<int> RemoveSmallest(List<int> numbers)
    {
        var lowestIndex = -1;
        var lowest = Int32.MaxValue;
    
        for (var i = 0; i < numbers.Count; i++)
        {
            if (numbers[i] < lowest) {
                lowest = numbers[i];
                lowestIndex = i;
            }
        }
    
        var newList = new List<int>(numbers);
        newList.RemoveAt(lowestIndex);
    
        return newList;
    

    }

    【讨论】:

    • OP:“我意识到在重复的列表中使用 Min 和 Remove(或类似的)会更容易,但我故意让自己的生活变得艰难。”
    • 这将抛出一个ArgumentOutOfRangeException 问题中提供的示例输入
    • 您可能希望将“最低”设置为 int.MaxValue
    • 更正,初始值应该更大
    • 您不将最低设置为 int.MaxValue 或 int.MinValue,您只需将其设置为数组中的第一项。看我的回答。
    【解决方案4】:

    虽然使用嵌套循环并没有错,但你也可以不用。基本上,您可以在迭代之前将列表中的第一个元素视为最小的元素,然后遍历列表以检查是否有任何其他数字小于已选择的数字,如果是这种情况,则更新 lowest 变量适当地并按照列表进行。

    这里有完整的解决方案:

    public static List<int> RemoveSmallest(List<int> numbers)
    {
    
           if(numbers == null) throw new ArgumentNullException("null argument");
           if (numbers.Count < 1) return numbers;
    
           var newList = new List<int>();
           var lowest = numbers[0]; // treat this as the smallest
    
           for (int i = 1; i < numbers.Count; i++)
           {
                if (numbers[i] < lowest) // compare it against other elements
                {
                    lowest = numbers[i]; // update lowest
                }
    
           }
    
           foreach (var num in numbers)
           {
                if (num != lowest)  // dont add the lowest
                {
                    newList.Add(num);
                }
           }
    
           return newList;
    }
    

    【讨论】:

    • 这与Benjamin's answer 的答案几乎完全相同。您只添加了简短的文字说明,if (numbers.Count &lt; 1) return numbers; 我认为这更适合作为对本杰明答案的评论或编辑。
    • 这还是两个循环。
    • @john 我的评论说“嵌套循环”
    • @OusmaneMahyDiaw 不,它没有。不过很好editing after the fact
    • @john Ousmane 指的是this comment
    猜你喜欢
    • 2018-02-16
    • 2011-01-04
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多