In the scenario I present to you, my solution is supposed to represent O(n^2*对数n), and the "pointers" solution, which I assume is the fastest way to resolve the "3SUM" problem, represents O(n^2 * 1); leaving the question of is O(1) faster than O(log n), exampling it with my code.
Could someone explain why this seems to be the case? Please. My logic tells me that O(log n) should be as fast as O(1), if not faster.
I hope my comments on the code of my solution are clear.

Edit:我知道这听起来不太明智…log(n)计算输入(n->∞), 虽然1…只是1.但是,在这种情况下,对于查找数字,如何更快地进行求和和和减法,而不是使用二进制搜索(log n)?它只是没有进入我的脑海.


LeetCode 3SUM问题描述


O(n^2*对数n)

对于3000个值的输入:

  • 迭代次数:1,722,085 (61% less than the "pointers solution")
  • 运行时间:~92 ms (270% slower than the typical O(n^2) solution)
public IList<IList<int>> MySolution(int[] nums)
{
    IList<IList<int>> triplets = new List<IList<int>>();

    Array.Sort(nums);

    for (int i = 0; i < nums.Length; i++)
    {
        // Avoid duplicating results.
        if (i > 0 && nums[i] == nums[i - 1])
            continue;

        for (int j = i+1; j < nums.Length - 1; j++)
        {
            // Avoid duplicating results.
            if (j > (i+1) && nums[j] == nums[j - 1])
                continue;

            // The solution for this triplet.
            int numK = -(nums[i] + nums[j]);

            // * This is the problem.
            // Search for 'k' index in the array.
            int kSearch = Array.BinarySearch(nums, j + 1, nums.Length - (j + 1), numK);

            // 'numK' exists in the array.
            if (kSearch > 0)
            {
                triplets.Add(new List<int>() { nums[i], nums[j], numK });
            }
            // 'numK' is too small, break this loop since its value is just going to increase.
            else if (~kSearch == (j + 1))
            {
                break;
            }
        }
    }

    return triplets;
}

O(n^2)

对于3000个值的相同输入:

  • 迭代次数:4.458.579
  • 运行时间:~34 ms
public IList<IList<int>> PointersSolution(int[] nums)
{
    IList<IList<int>> triplets = new List<IList<int>>();

    Array.Sort(nums);

    for (int i = 0; i < nums.Length; i++)
    {
        if (i > 0 && nums[i] == nums[i - 1])
            continue;

        int l = i + 1, r = nums.Length - 1;

        while (l < r)
        {
            int sum = nums[i] + nums[l] + nums[r];

            if (sum < 0)
            {
                l++;
            }
            else if (sum > 0)
            {
                r--;
            }
            else
            {
                triplets.Add(new List<int>() { nums[i], nums[l], nums[r] });

                do
                {
                    l++;
                }
                while (l < r && nums[l] == nums[l - 1]);
            }
        }
    }

    return triplets;
}

推荐答案

你的概念误解似乎来自这样一个事实,即你错过了Array.BinarySearch也做了一些迭代(这是由你现在已经更改的问题中的初始迭代计数表示的).

因此,虽然假设二元搜索应该比通过集合进行的简单迭代更快是非常有效的,但您缺少了二元搜索基本上是一个额外的循环,因此您不应该比较这两个循环,而是应该将第一个解决方案中的第二个for循环+二元搜索与第二个解决方案中的第二个循环进行比较.

附笔.

为了在一定程度上确定基于运行时的时间复杂度,您至少需要使用不同数量的元素(如100、1000、10000、100000…)执行多个测试,并查看运行时是如何变化的.同样,对于相同数量的元素,建议使用不同的输入,因为在理论上,一种算法可能会遇到一些最佳情况,而另一种算法则可能会遇到最坏情况.

Csharp相关问答推荐

如何从泛型方法返回一个可为空的T,其中T:notnull?

如何在NServicebus中配置学习传输的文件夹(NService bus 8)

解析需要HttpClient和字符串的服务

Elasticsearch:当我try 使用c#将嵌套对象添加到filter中时出现问题

try 还原包时出错:Dapper已经为System.Data.SQLClient定义了依赖项''''

如何阻止注释被包含在C#release build. exe中

Microsoft. VisualBasic. FileIO. FileSystem. MoveFile()对话框有错误?

当通过Google的Gmail Api发送邮件时,签名会产生dkim = neutral(正文散列未验证)'

.NET HttpClient、JsonSerializer或误用的Stream中的内存泄漏?

默认情况下,.NET通用主机(Host.CreateDefaultBuilder)中是否包含UseConsoleLifetime?

如何在C#中从正则表达式中匹配一些数字但排除一些常量(也是数字)

当索引和外键是不同的数据类型时,如何设置导航属性?

异步任务调用程序集

Azure函数-在外部启动类中生成配置时出错

如何正确处置所有动态控件?

C# Winforms:从对象树到TreeView的递归转换重复条目

如何使用IHostedService添加数据种子方法

如何从SignalR获取连接客户端的域

无法使用直接URL通过PictureBox.ImageLocation加载图像

我是否以错误的方式使用了异步延迟初始化?