public void Union_ConnectTwoElements_Should_BeConnected() { // Arrange var qf = new QuickUnion(10); // Act qf.Union(1, 2); // Assert Assert.True(qf.Connected(1, 2)); }
public void TestQuickUnion() { var input = new List <int[]>() { new int[] { 1, 3 }, new int[] { 1, 4 }, new int[] { 8, 9 } }; var N = 10; var uf = new QuickUnion(N); foreach (var item in input) { uf.Union(item[0], item[1]); } Assert.Equal(uf.Connected(3, 4), true); Assert.Equal(uf.Connected(9, 0), false); }
public void Union_ConnectedSequence_Should_BeConnected() { // Arrange var qf = new QuickUnion(10); // Act qf.Union(1, 2); qf.Union(3, 2); qf.Union(4, 3); // Assert Assert.True(qf.Connected(1, 4)); }
public void QuickFind_TinyFile_True() { var dots = new Dots(@"DataStore\tinyUF.txt"); var quickUnion = new QuickUnion(dots.Count); foreach (Tuple <int, int> item in dots.Items) { if (quickUnion.Connected(item.Item1, item.Item2)) { continue; } quickUnion.Union(item.Item1, item.Item2); } Assert.Equal(2, quickUnion.Count); }
/// <summary> /// assume that maximum number of cities is 50 /// Map new road as integer quickly. /// using SortedDictionary /// https://github.com/jianminchen/Leetcode_Julia/blob/master/source%20code/23%20Merge%20K%20sorted%20lists%20-%20using%20minimum%20heap.cs /// </summary> /// <param name="noCities"></param> /// <param name="existingRoads"></param> /// <param name="newRoads"></param> /// <param name="roadWithCost"></param> /// <returns></returns> public static int getMinimumCost( int noCities, List <int[]> existingRoads, int newRoads, List <int[]> roadWithCost) { var quickUnion = new QuickUnion(noCities); foreach (var item in existingRoads) { // adjust the value of id from 0 to N - 1 quickUnion.Union(item[0] - 1, item[1] - 1); } int count = quickUnion.GetCount(); var newRoadMap = new SortedDictionary <int, Queue <int[]> >(); foreach (int[] item in roadWithCost) { var id1 = item[0] - 1; var id2 = item[1] - 1; var roadCost = item[2]; if (!newRoadMap.ContainsKey(roadCost)) { newRoadMap.Add(roadCost, new Queue <int[]>()); } newRoadMap[roadCost].Enqueue(new int[] { id1, id2 }); } var totalCost = 0; while (newRoadMap.Count > 0) { int minCost = newRoadMap.First().Key; var ids = newRoadMap[minCost].Dequeue(); if (newRoadMap[minCost].Count == 0) { newRoadMap.Remove(minCost); } var id1 = ids[0]; var id2 = ids[1]; var connected = quickUnion.Connected(id1, id2); if (connected) { continue; } totalCost += minCost; quickUnion.Union(id1, id2); // Union, not Connected if (quickUnion.GetCount() == 1) { break; } } if (quickUnion.GetCount() > 1) { return(-1); } return(totalCost); }
/// <summary> /// Leetcode 721 /// https://leetcode.com/problems/accounts-merge/ /// </summary> /// <param name="accounts"></param> /// <returns></returns> public static IList <IList <string> > AccountsMerge(IList <IList <string> > accounts) { var emailSet = getAllEmails(accounts); // https://leetcode.com/problems/accounts-merge/discuss/164699/C-Solution-(Union-Find)-beats-91.49 var emailList = emailSet.ToList(); var ordCmp = StringComparer.Ordinal; emailList.Sort(ordCmp); var emailNameMap = getEmailNameMap(accounts); var emailIdmap = new Dictionary <string, int>(); int index = 0; var emailLookup = new List <string>(); foreach (var item in emailList) { emailIdmap.Add(item, index); index++; emailLookup.Add(item); } var unionFind = new QuickUnion(emailSet.Count); unionFind.EmailIdMap = emailIdmap; foreach (var list in accounts) { for (int i = 1; i < list.Count - 1; i++) { var email1 = list[i]; var email2 = list[i + 1]; var connected = unionFind.Connected(email1, email2); if (!connected) { unionFind.Union(email1, email2); } } } // flat the tree for (int i = 0; i < emailSet.Count; i++) { unionFind.QuickFindAndPathCompression(i); } var dict = new Dictionary <int, List <string> >(); var parent = unionFind.GetParent(); for (int i = 0; i < parent.Length; i++) { var key = parent[i]; if (!dict.ContainsKey(key)) { dict.Add(key, new List <string>()); } dict[key].Add(emailLookup[i]); } // output a list var result = new List <IList <string> >(); foreach (var item in dict.Keys) { var list = new List <string>(); var email = emailLookup[item]; var name = emailNameMap[email]; list.Add(name); var values = dict[item]; list.AddRange(values); result.Add(list); } return(result); }
/// <summary> /// assume that maximum number of cities is 50 /// Map new road as integer quickly. /// </summary> /// <param name="noCities"></param> /// <param name="existingRoads"></param> /// <param name="newRoads"></param> /// <param name="roadWithCost"></param> /// <returns></returns> public static int getMinimumCost( int noCities, List <int[]> existingRoads, int newRoads, List <int[]> roadWithCost) { var quickUnion = new QuickUnion(noCities); foreach (var item in existingRoads) { // adjust the value of id from 0 to N - 1 quickUnion.Union(item[0] - 1, item[1] - 1); } int count = quickUnion.GetCount(); var newRoadMap = new Dictionary <int, List <int> >(); foreach (int[] item in roadWithCost) { var id1 = item[0] - 1; var id2 = item[1] - 1; var roadCost = item[2]; var newId = id1 * 50 + id2; if (!newRoadMap.ContainsKey(roadCost)) { newRoadMap.Add(roadCost, new List <int>()); } newRoadMap[roadCost].Add(newId); } var costs = newRoadMap.Keys.ToArray(); Array.Sort(costs); var length = costs.Length; var totalCost = 0; for (int i = 0; i < length; i++) { var current = costs[i]; var ids = newRoadMap[current]; foreach (var id in ids) { var id1 = id % 50; var id2 = id / 50; var connected = quickUnion.Connected(id1, id2); if (connected) { continue; } totalCost += current; quickUnion.Union(id1, id2); // Union, not Connected } } if (quickUnion.GetCount() > 1) { return(-1); } return(totalCost); }