繁体   English   中英

如何使用嵌套循环降低 C# 方法的时间复杂度

[英]How to reduce time complexity of a C# method with nested loops

我正在使用 Kubernetes C# 客户端通过更改具有特定图像名称的容器中的图像标签来修补集群中的部署。

根据我对二次时间复杂度 O(n2) 的了解,我的第一个版本的方法似乎效率不高。

private List<V1Deployment> UpdateImageTag(string imageName, string tag, List<V1Deployment> deployments)
        {
            var updatedDeployments = new List<V1Deployment>();

            if (deployments?.Count > 0)
            {
                foreach (var deployment in deployments)
                {
                    foreach (var container in deployment?.Spec?.Template?.Spec?.Containers.SkipWhile(x => !x.Image.ToLowerInvariant()
                                                                                                            .StartsWith(imageName.ToLowerInvariant())))
                    {
                        if (container is null)
                        {
                            // Log it and go to the next container.
                            _logger.LogDebug("Deployment {Deployment} has a null container, skipping it.", deployment?.Metadata?.Name);
                            continue;
                        }
                        SetImageTag(tag, container);

                        if (!updatedDeployments.Contains(deployment))
                        {
                            updatedDeployments.Add(deployment);
                        }
                    }
                }
            }

            return updatedDeployments;
        }

如何以更有效的方式实现这一目标?

与评论相反,最坏情况的时间复杂度实际上是O(n^2) ,其中ndeployment的长度。 但这不是因为嵌套的foreach 这是因为对Contains的调用。 实际上它比这更糟糕 - 复杂性更准确地说是O(m*n^2) ,其中m是每个部署的容器数量,因为Contains在内部循环中。

这样做怎么样(复杂度为O(m*n) ,这是给定输入数据结构的最佳选择):

    private List<V1Deployment> UpdateImageTag(string imageName, string tag, List<V1Deployment> deployments)
    {
        if (deployments == null)
        {
            return new List<V1Deployment>();
        }

        var imageNameLower = imageName.ToLowerInvariant();

        var matches = deployments
            .Select(deployment => KeyValuePair.Create(
                deployment, 
                deployment.Spec?.Template?.Spec?.Containers
                    .Where(c => !c.Image.ToLowerInvariant().StartsWith(imageNameLower))))
            .Where(kvp => kvp.Value != null)
            .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
            

        foreach (var container in matches.Values.SelectMany(x => x))
        {
            SetImageTag(tag, container);
        }

        return matches.Keys.ToList();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM