搜索重复时的时间复杂性问题

时间:2018-05-03 18:46:20

标签: c# time-complexity

我的代码返回正确的答案,第一个副本是3.我正在努力解决时间问题。有没有更有效的方法来找到第一个副本?

我的约束是1≤a.length≤10^5,1≤a[i]≤a.length。感谢。

class Program
{
    static void Main(string[] args)
    {
        int[] a = { 1, 2, 3, 4, 5, 6 };

        int f = FirstDuplicate(a);
        Console.ReadLine();
    }
    public static int FirstDuplicate(int[] a)
    {

        int[] answer = new int[2];
        answer[0] = -1;
        answer[1] = a.Length;
        for (int i = 0; i < a.Length - 1; i++)
            for (int j = i; j < a.Length; j++)
                if (a[i] == a[j] && i != j)
                {
                    if (i < answer[1])
                    {
                        answer[0] = a[i];
                        answer[1] = j;
                        break;

                    }
                }

        return answer[0];

2 个答案:

答案 0 :(得分:2)

你说

  

1≤a.length≤105,

  

我正在努力应对时间的复杂性。有没有更有效的方法来找到第一个副本?

你的问题是荒谬的;鉴于约束,你的程序是O(1)。 任何问题大小较小的程序都是O(1)

假设我们放松了数组长度非常小的条件。在这种情况下,显然你的方法是二次的。

有线性解决方案。它是:

seen = an empty set
for each element x of the array
  if seen contains x then 
    return value x
  else 
    seen = seen with x
end for
return not found

这是数组的大小线性,前提是测试集合的包含和增长集合是恒定的时间

你能想出一种方法来制作一组整数,以便检查该组中的成员资格是恒定时间,并且向该集合添加新成员是恒定时间吗?

提示:你能否使用数组中的值是小整数这一事实?

练习:现在执行问题,不要对数组大小或其内容大小的任何约束。

练习:现在对任意类型T执行问题,如果T.Equals(T)返回true,则两个Ts相等。

答案 1 :(得分:0)

我认为你可以做一些改进。与当前代码相比,项目#3,#4和#5都将减少迭代次数:

  1. 我们需要实际比较a[i]a[j]的值,看看我们是否发现重复。
  2. j的索引存储在变量中,如果它小于当前值(我们初始化为int.MaxValue,那么第一个匹配将自动添加)。
  3. 如果ij大于最小重复索引,则添加条件退出循环,因为此时的任何匹配都会自动过大。 < / LI>
  4. 外部循环只需转到i < a.Length - 1,因为我们会将其与下一个值进行比较(a.Length之后没有值)
  5. 内部循环可以从i + 1开始,以避免对我们已经比较的索引进行比较
  6. 以下是一个例子:

    /// <summary>
    /// Gets the index of the first duplicate item in an array
    /// </summary>
    /// <param name="a">The array to search</param>
    /// <returns>The index of the first duplicate item, or -1 if none exist</returns>
    public static int FirstDuplicate(int[] a)
    {
        if (a == null || a.Length < 2) return -1;
    
        var smallestDupeIndex = int.MaxValue;
    
        for (int i = 0; i < a.Length - 1 && i < smallestDupeIndex; i++)
        {
            for (int j = i + 1; j < a.Length && j < smallestDupeIndex; j++)
            {
                if (a[i] == a[j])
                {
                    smallestDupeIndex = j;
                }
            }
        }
    
        return smallestDupeIndex == int.MaxValue ? -1 : smallestDupeIndex;
    }
    

    这里正在使用,有一个包含许多重复项的数组:

    private static void Main()
    {
        int[] a = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    
        Console.Write(GetFirstDupeIndex(a));
    
        GetKeyFromUser("\nDone! Press any key to exit...");
    }
    

    <强>输出

    enter image description here