【问题标题】:Reorder a unique list to another by movings in the original list通过在原始列表中移动将唯一列表重新排序到另一个列表
【发布时间】:2020-09-29 17:51:45
【问题描述】:

我正在寻找任何命令式编程语言中的算法,通过在原始列表中移动来将唯一列表重新排序到另一个列表。

输入:

items       = [a, b, c, d, e]
sampleItems = [b, c, e, d, a]

输出:

items   =     [b, c, e, d, a]

itemssampleItems 中的项目集是相等的。

应通过移动原始列表(items)来执行重新排序。

void Move(int oldIndex, int newIndex)
{
  Item item = items[oldIndex];
  items.RemoveAt(oldIndex);
  items.Insert(item, newIndex);
}

所以 items 列表在所有重新排序期间保存了它的唯一性。

算法应该尽可能高效,不创建字典等额外的数据结构,并且具有最少的移动量和最小的复杂性。

蛮力方法是按新索引进行冒泡排序。但它需要创建字典(键:项目,值:新索引)或样本列表上的大量枚举(sampleItems)。我正在寻找更有效的方法。

我尝试了以下算法(C#),它可以正常工作,但效率不高,因为它创建了一个字典并且具有 O(n^2) 复杂度。处理 10001 个项目大约需要 9 秒。很慢:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp14
{
	class Program
	{
		static void Main(string[] args)
		{
			ObservableCollection<Item> items = new ObservableCollection<Item>();

			int count = 10001;

			for (int i = 0; i < count; i++)
			{
				items.Add(new Item(i));
			}

			Random random = new Random();			
			ObservableCollection<Item> sampleItems = new ObservableCollection<Item>(items.OrderBy(i => random.Next()));
			
			Stopwatch stopwatch = Stopwatch.StartNew();
			Dictionary<Item, int> oldIndeces = new Dictionary<Item, int>();
			for (int i = 0; i < count; i++)
			{
				oldIndeces.Add(items[i], i);
			}

			for (int i = 0; i < count; i++)
			{
				int oldIndex = oldIndeces[sampleItems[i]];
				items.Move(oldIndex, i);

				for (int j = 0; j < count; j++)
				{
					Item item = items[j];
					int oldIndex1 = oldIndeces[item];
					if (oldIndex1 <= oldIndex)
						oldIndeces[item] = oldIndex1 + 1;
				}
			}

			Debug.Assert(sampleItems.SequenceEqual(items));
			stopwatch.Stop();
			Console.WriteLine($"Done in {stopwatch.ElapsedMilliseconds}ms");
			Console.ReadLine();
		}
	}

	public class Item
	{
		public Item(int num)
		{
			Num = num;
		}

		private int Num { get; }

		#region Overrides of Object

		public override string ToString()
		{
			return Num.ToString();
		}

		#endregion
	}
}

输出:

在 9123 毫秒内完成

【问题讨论】:

    标签: list algorithm sorting language-agnostic unique


    【解决方案1】:

    这是一个没有字典的实现:

    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Linq;
    
    namespace ConsoleApp14
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			ObservableCollection<Item> items = new ObservableCollection<Item>();
    
    			int count = 10001;
    
    			for (int i = 0; i < count; i++)
    			{
    				items.Add(new Item(i));
    			}
    
    			Random random = new Random();			
    			ObservableCollection<Item> sampleItems = new ObservableCollection<Item>(items.OrderBy(i => random.Next()));
    			
    			Stopwatch stopwatch = Stopwatch.StartNew();
    			int oldIndex = 0;
    			Item sampleItem;
    			Item nextSampleItem = null;
    			for (int i = 0; i < count; i++)
    			{
    				sampleItem = sampleItems[i];
    				if (i < count - 1) nextSampleItem = sampleItems[i + 1];
    
    				if (i == 0)
    				{
    					for (int j = 0; j < count; j++)
    					{
    						if (sampleItem == items[j])
    							oldIndex = j;
    					}
    				}
    
    				items.Move(oldIndex, i);
    
    				for (int j = i + 1; j < count; j++)
    				{
    					if (items[j] == nextSampleItem)
    					{
    						oldIndex = j;
    					}
    				}
    			}
    
    			Debug.Assert(sampleItems.SequenceEqual(items));
    			stopwatch.Stop();
    			Console.WriteLine($"Done in {stopwatch.ElapsedMilliseconds}ms");
    			Console.ReadLine();
    		}
    	}
    
    	public class Item
    	{
    		public Item(int num)
    		{
    			Num = num;
    		}
    
    		private int Num { get; }
    
    		#region Overrides of Object
    
    		public override string ToString()
    		{
    			return Num.ToString();
    		}
    
    		#endregion
    	}
    }

    在 533 毫秒内完成

    此实现也适用于非唯一列表。

    【讨论】:

      猜你喜欢
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-12
      • 1970-01-01
      • 2015-02-27
      相关资源
      最近更新 更多