从索引存在于另一个数组中的一个数组中删除元素

时间:2015-01-02 13:39:00

标签: c# arrays algorithm

包含N个对象的数组A1。另一个包含表示第一个数组中索引的数字的数组A2。您需要从A2中删除A2中的索引所在的元素并生成压缩数组。例如:

A1 = [ a, b, c, d, e, f, g ] // N elements and N is large
A2 = [ 5, 1 ] // k elements and k is small (and constant)
Answer = [ a, c, d, e, g, _, _ ]

我写了C#代码,如:

public class CompactingArray
{
    private Compact(array A1 , array A2)
    {
        var hash = new Hashset<int>(A2);
        foreach(int c in hash)
        {
            A1.remove(c,1);
        }

        Console.WriteLine(A1);
    }
}

我需要O(n)复杂度代码而不使用任何内置函数。请在不使用任何内置函数的情况下建议使用C#代码。

3 个答案:

答案 0 :(得分:5)

这是解决方案。

        Char[] A1 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
        int[] A2 = { 5, 1 };

        int k = A2.Length;

        int N = A1.Length;

        for (int i = 0; i < k; i++)
        {
            A1[A2[i]] = '\0'; // place null charcater here
        }

        Char[] copy = new char[N];

        for (int i = 0,j=0; i < N; i++) // place all values in sorted order
        {
            if (A1[i] != '\0')
                copy[j++] = A1[i];
        }
        for (int i = (N-k); i < N;i++ )
        {
            copy[i] = '-';
        }
        Console.WriteLine(copy);

答案 1 :(得分:0)

结果数组的顺序是否重要?如果没有,你可以做一些事情:

char[] a = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
int[] z = { 5, 1 };

int zlen = z.Length;
int amax = a.Length - 1;

for (int i = 0; i < zlen; i++)
    a[z[i]] = a[amax - i];

最后,您必须调整生成的数组(a本身)的大小,以便从数组的末尾删除zlen个元素。该解决方案只是将要移除的元素冒泡到数组的末尾。无需顺序删除。添加正确的索引边界检查等。

答案 2 :(得分:-2)

如果O(n)被排序,则

A2复杂性是可能的,因为那样你只需要一个循环就可以分别为每个数组编制索引:

var A1 = new string[] { "a", "b", "c", "d", "e", "f", "g" }; // N elements and N is large

var A2 = new int[] { 1, 5 }; // k elements and k is small (and constant)

A2 = A2.OrderBy(x => x).ToArray();

var A3 = new string[A1.Length];

int m = 0; // To check it runs only n times.
int leftItemCount = A1.Length - A2.Length;
for (int i = 0, j = 0, k = 0, l = leftItemCount; i < leftItemCount || m < items.Length; i++)
{
    m++;
    if (j < A2.Length && k == A2[j])
    {
        j++;
        k++;
        A3[l++] = "_";
        i--;
        continue;
    }
    A3[i] = A1[k];
    k++;
}

// Answer = [ a, c, d, e, g, _, _ ] for { 1, 5 }
// Answer = [ a, d, e, g, _, _, _ ] for { 1, 2, 5 }

测试代码:

static void ArrayTests()
{
    // Item array lengths.
    for (int i = 45; i < 256; i++)
    {
        var items = Enumerable.Range(0, i).Select(x => x.ToString()).ToArray();

        // Number of tests per array.
        for (int j = 0; j < 100; j++)
        {
            // Items to remove.
            Random rnd = new Random(DateTime.Now.Millisecond);
            var remove = new int[rnd.Next(1, i)];
            HashSet<int> indexes = new HashSet<int>();
            for (int k = 0; k < remove.Length; k++)
            {
                int index = 0;
                do
                {
                    index = rnd.Next(0, i);
                } while (indexes.Contains(index));
                indexes.Add(index);
                remove[k] = index;
            }
            remove = remove.OrderBy(x => x).ToArray();
            var result = ArrayTest(items, remove);
        }
    }
}

static string[] ArrayTest(string[] items, int[] remove)
{
    var A3 = new string[items.Length];

    int m = 0;
    int leftItemCount = items.Length - remove.Length;
    for (int i = 0, j = 0, k = 0, l = leftItemCount; i < leftItemCount || m < items.Length; i++)
    {
        m++;
        if (j < remove.Length && k == remove[j])
        {
            j++;
            k++;
            A3[l++] = "_";
            i--;
            continue;
        }
        A3[i] = items[k];
        k++;
    }            
    Debug.Assert(m == items.Length);
    return A3;
}