特殊排序之红白球
特殊排序之红白球
今天去面试,做了一道上机题,感觉有点意思,记录一下。
设有红色、白色两种球若干,放在一个数组里,请实现算法:把红球排到白球前面。
先设置好要操作的类:
红白球Ball
1 enum EBallColor 2 { 3 Red, 4 White, 5 } 6 class Ball : IComparable<Ball> 7 { 8 public EBallColor BallColor { get; set; } 9 public Ball(EBallColor color) 10 { 11 this.BallColor = color; 12 } 13 public override string ToString() 14 { 15 return string.Format("{0}", BallColor); 16 //return base.ToString(); 17 } 18 19 /// <summary> 20 /// Red > White 21 /// </summary> 22 /// <param name="other"></param> 23 /// <returns></returns> 24 public int CompareTo(Ball other) 25 { 26 if (other == null) 27 { 28 return -1; 29 } 30 31 if (this.BallColor == other.BallColor) 32 { 33 return 0; 34 } 35 36 if (this.BallColor == EBallColor.Red) 37 { 38 return 1; 39 } 40 41 return -1; 42 } 43 }
当然用排序的方式是可以的:
插入排序实现
1 private static void BallArrange(Ball[] ballList) 2 { 3 if (ballList == null || ballList.Length < 2) 4 { 5 return; 6 } 7 8 for (int i = 0; i < ballList.Length; i++) 9 { 10 int p = i; 11 12 for (int j = i + 1; j < ballList.Length; j++) 13 { 14 if (ballList[p].CompareTo(ballList[j]) < 0) 15 { 16 p = j; 17 } 18 } 19 20 if (p != i) 21 { 22 var tmp = ballList[p]; 23 ballList[p] = ballList[i]; 24 ballList[i] = tmp; 25 } 26 } 27 }
写的时候就想到排序是很浪费的,各个球没有大小,只有两个值,然后就想到直接把白球放到最后就可以了。于是又写了一种算法。(名字很猥琐)
抽插实现
1 static void BallArrange2(IList<Ball> ballList) 2 { 3 if (ballList == null || ballList.Count < 2) 4 { 5 return; 6 } 7 8 int arranged = 0, index = 0; 9 10 while (index < ballList.Count - arranged) 11 { 12 var ball = ballList[index]; 13 if (ball.BallColor == EBallColor.White) 14 { 15 ballList.Remove(ball); 16 ballList.Add(ball); 17 arranged--; 18 } 19 else 20 { 21 index++; 22 } 23 } 24 }
要是就这么简单,我觉得面试官不会拿来考我。所以应该有优化的算法。在人家明确提出用一次循环搞定问题之后。我想出了下面的算法。
左右交换实现
1 static void BallArrange3(Ball[] ballList) 2 { 3 if (ballList == null || ballList.Length < 2) 4 { 5 return; 6 } 7 8 int left = 0, right = ballList.Length - 1; 9 10 while (left < right) 11 { 12 if (ballList[left].BallColor == EBallColor.Red) 13 { 14 if (ballList[right].BallColor == EBallColor.Red) 15 { 16 left++; 17 } 18 else 19 { 20 left++; 21 right--; 22 } 23 } 24 else 25 { 26 if (ballList[right].BallColor == EBallColor.White) 27 { 28 right--; 29 } 30 else 31 { 32 var tmp = ballList[left]; 33 ballList[left] = ballList[right]; 34 ballList[right] = tmp; 35 left++; 36 right--; 37 } 38 } 39 } 40 }
写出来就觉得是对了,果然面试官说想要的就是这种“交换”的思路。
这个算法的思路是:从左开始,发现是红球的,说明符合条件,抛弃之不再管(left++);从右开始,发现是白球的,符合条件,抛弃之不再管(right--),只有左白右红时,交换,然后抛弃之不再管。直到left >= right时,左右都符合条件,结束。
最后面试官又问了一下Main函数里的测试代码的问题,说能不能只写一个BallArrange函数就实现多种排序算法的测试?我听明白了他想问什么,但是脑子一时堵塞,没有想起那个名词来,于是pardon了一下,然后就明白了,说可以对每个算法分别设置一个类,使其继承一个基类,BallArrange方法继承自基类的虚方法。后来回想起来,这个好像是策略模式吧。然后面试官就说没问题了,想问的就是这个了。
测试用例
1 static void Main(string[] args) 2 { 3 Ball[] ballList = new Ball[] 4 { 5 new Ball(EBallColor.Red), 6 new Ball(EBallColor.White), 7 new Ball(EBallColor.White), 8 new Ball(EBallColor.Red), 9 new Ball(EBallColor.Red), 10 }; 11 12 Console.WriteLine("Before arrange: "); 13 foreach (var item in ballList) 14 { 15 Console.WriteLine(item); 16 } 17 18 //BallArrange(ballList); 19 //BallArrange2(ballList); 20 BallArrange3(ballList); 21 22 Console.WriteLine("After arrange: "); 23 foreach (var item in ballList) 24 { 25 Console.WriteLine(item); 26 } 27 }
微信扫码,自愿捐赠。天涯同道,共谱新篇。
微信捐赠不显示捐赠者个人信息,如需要,请注明联系方式。 |