You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将存储苏打饮料的对象数组中null元素高效排序至末尾?

解决方案:高效维护非null元素在前的数组

首先,咱们先理清楚你的核心需求:给存储Soda的object数组实现删除指定对象的方法,同时要保证所有非null的Soda对象始终排在数组前半部分,null元素统一移到末尾,还要尽可能高效。

先纠正你代码里的小细节:你的数组变量是bottleVector,但后面写了bottles.Sort(),应该是笔误,咱们统一用bottleVector来指代这个数组;另外数组默认的Sort()方法是按对象默认规则排序,完全不符合咱们“把null移到末尾”的需求,得换个思路。

一、高效整理数组:双指针法(O(n)时间复杂度)

比起用Sort()做全排序(O(n log n)),双指针法只需要一次遍历就能完成null元素的后置,效率更高。核心逻辑很简单:

  • 左指针从数组开头出发,找第一个null元素
  • 右指针从数组末尾出发,找最后一个非null元素
  • 交换两者位置,重复直到左指针超过右指针

实现这个逻辑的方法:

private void RearrangeBottles()
{
    int left = 0;
    int right = bottleVector.Length - 1;

    while (left < right)
    {
        // 左指针定位第一个null
        while (left < right && bottleVector[left] != null)
        {
            left++;
        }
        // 右指针定位最后一个非null
        while (left < right && bottleVector[right] == null)
        {
            right--;
        }
        // 交换位置,继续向中间靠拢
        if (left < right)
        {
            (bottleVector[left], bottleVector[right]) = (bottleVector[right], bottleVector[left]);
            left++;
            right--;
        }
    }
}

二、实现删除指定Soda对象的方法

删除逻辑很直接:遍历数组找到目标Soda对象,把它设为null,然后调用上面的RearrangeBottles()整理数组。如果需要删除所有匹配的重复对象,去掉代码里的break即可。

public void RemoveSoda(Soda targetSoda)
{
    if (targetSoda == null) return;

    // 遍历找到目标对象并置为null
    for (int i = 0; i < bottleVector.Length; i++)
    {
        if (bottleVector[i] is Soda soda && soda.Equals(targetSoda))
        {
            bottleVector[i] = null;
            break; // 假设每个Soda唯一,找到就退出遍历
        }
    }

    // 整理数组,把所有null移到末尾
    RearrangeBottles();
}

⚠️ 重要补充:为了让Equals方法能正确识别相同的Soda对象,最好给Soda类重写Equals和GetHashCode方法:

class Soda {
    public string name;
    public double price;

    public Soda(string _name, double _price) {
        name = _name;
        price = _price;
    }

    // 重写Equals确保正确比较Soda对象
    public override bool Equals(object obj)
    {
        if (obj is Soda other)
        {
            // 浮点数比较用精度判断,避免精度误差
            return name == other.name && Math.Abs(price - other.price) < 1e-9;
        }
        return false;
    }

    // 必须和Equals配对重写GetHashCode
    public override int GetHashCode()
    {
        return HashCode.Combine(name, price);
    }
}

三、优化Add方法(可选)

你的add_soda方法原本想调用Sort(),其实更高效的方式是直接找到第一个null位置插入,这样插入后非null元素自然都在前面,不需要额外整理:

public bool AddSoda(Soda newSoda)
{
    if (newSoda == null) return false;

    // 找到第一个空位置插入
    for (int i = 0; i < bottleVector.Length; i++)
    {
        if (bottleVector[i] == null)
        {
            bottleVector[i] = newSoda;
            return true;
        }
    }

    // 数组已满,返回插入失败
    return false;
}

为什么不用Sort()?

Array.Sort()本质是全排序,对于咱们只需要“把null移到末尾”的需求来说完全是冗余操作。双指针法只需要一次遍历,时间复杂度O(n),比Sort的O(n log n)高效得多——哪怕你的数组只有24个元素,逻辑上也更贴合需求。

如果一定要用Sort的方式,也可以自定义比较器,但效率不如双指针:

Array.Sort(bottleVector, (a, b) => 
{
    if (a == null && b == null) return 0;
    if (a == null) return 1; // null排后面
    if (b == null) return -1; // 非null排前面
    return 0; // 非null元素保持原有顺序
});

内容的提问来源于stack exchange,提问作者Daniel Slätt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:10:36