在一次采访中,我被问到以下问题,我得到了一个整数数组,我需要返回该数组中整数的数量,这些整数不在索引中(如果对数组进行排序的话)。 / p>
例如对于数组[1,1,3,4,1],我需要返回3,因为最后三个整数(3,4,1)不在索引中,如果数组是排序为[1,1,1,3,4]。 对于[5,4,3,2,1],我需要返回4,([1,2,3,4,5])。
我只想出了一个简单的解决方案,即复制原始数组,然后对其进行排序并比较两个数组,然后计算每个索引中不同元素的数量。 这需要O(nlogn)时间和O(n)空间。
在我看来,也许我错过了一些东西,也许会有更好的解决方案。有更好的解决方案吗?
答案 0 :(得分:0)
天真意味着缺乏智慧/判断力;相反,在压力下获得简单,优雅的解决方案就相反。
可能还有改进的余地,但是如果存在,它就不太可能是“显而易见的”,而且可能也不简单。 (除了下面的实验,我的实验没有证明任何东西;-)
思考
对于要放置的项目,其左侧(在数组中的前面)较大项目的数量必须等于其右侧较小项目的数量。
很明显,无需第二个数组即可确定。下面的代码具有更好的空间复杂度O(1),但时间复杂度更差O(n ^ 2)。原谅局促的风格和递归,但我试图保持简洁。
using System;
using System.Text;
namespace ConsoleApp2
{
static class Program
{
private static int itemVisits;
static string PrintArray(int[] arr)
{
var sb = new StringBuilder("[");
foreach (var i in arr)
sb.AppendFormat("{0}, ", i);
sb.Length -= 2;// kill last comma and space
sb.Append("]");
return sb.ToString();
}
static void Test(int[] arr)
{
Console.WriteLine($"{PrintArray(arr)}...");
Console.WriteLine($" method1: {ItemsOutOfPlace1(arr)} elements out of place, {itemVisits} item visits");
// Console.WriteLine($" method2: {ItemsOutOfPlace2(arr)} elements out of place, {itemVisits} item visits");
}
static int ItemsOutOfPlace1(int[] arr)
{
int countOutOfPlace = 0;
itemVisits = 0;
for (int i = 0; i < arr.Length; i++)
countOutOfPlace += NeedToMove(arr[i], i) != 0 ? 1 : 0;
return countOutOfPlace;
// In place functions follow...
int NeedToMove(int val, int i) { return CountRightLessThan(val, i + 1) - CountLeftGreaterThan(val, i - 1); }
int CountRightLessThan(int val, int i)
{
if (i >= arr.Length) return 0;
itemVisits++;
return (arr[i] < val ? 1 : 0) + CountRightLessThan(val, i + 1);
}
int CountLeftGreaterThan(int val, int i)
{
if (i < 0) return 0;
itemVisits++;
return (arr[i] > val ? 1 : 0) + CountLeftGreaterThan(val, i - 1);
}
}
static void Main(string[] args)
{
Test(new []{ 1,1,3,4,1 });
Test(new []{ 5, 4, 3, 2, 1 });
Test(new []{ 2,3,4,1,6,7,8,9,5 });
Test(new []{ 30,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,1 });
Console.ReadKey();
}
}
}
生产
[1, 1, 3, 4, 1]...
method1: 3 elements out of place, 20 item visits
[5, 4, 3, 2, 1]...
method1: 4 elements out of place, 20 item visits
[2, 3, 4, 1, 6, 7, 8, 9, 5]...
method1: 9 elements out of place, 72 item visits
[30, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 1]...
method1: 2 elements out of place, 870 item visits
严格地是T(n(n-1))。我试图对此进行改进(您可能会发现对ItemsOutOfPlace2()
的注释引用),但没有排序,仅实现了最佳情况时间O(nlog(n)),并且需要回到O(n)空间,并且需要更多,更简洁的代码。
结论
好问题