2013-03-23
圆桌问题:圆桌上围坐着2n个人。其中n个人是好人,另外n个人是坏人。如果从第一个人开始数数,数到第m个人,则立即处死该人;然后从被处死的人之后开始数数,再将数到的第m个人处死…依此方法不断处死围坐在圆桌上的人。试问预先应如何安排这些好人与坏人的座位,能使得在处死n个人之后,圆桌上围坐的剩余的n个人全是好人
简化版:圆桌上坐着n个人,从第一个开始计数,偶数的人推出,最后剩下那个位置的人。
思路:数据结构,首先想到了C#提供的System.Collections.IList,思路很简单,foreach IList中每个记录,count用来计数,若count为偶数,删除之。但想到微软面试要用基元类型,想到两种类型:一个是用数组,一个自定义LinkList,而且要实现Iretator模式,下面是数据结构代码:
View Code
1 public interface IMyEnumerator<T> 2 { 3 int Length { get; } 4 T Current { get; } 5 bool MoveNext(); 6 void Reset(); 7 void Remove(T element); 8 } 9 10 //以数组结构存储数据,Length为实际记录数,Remove一个元素后,其后的记录向前移,Current为当前指向记录 11 public class SqArray1 : IMyEnumerator<int> 12 { 13 int[] _arr; 14 int _validLength; 15 int _index; 16 public SqArray1(int[] arr) 17 { 18 _arr = new int[arr.Length]; 19 arr.CopyTo(_arr, 0); 20 _validLength = arr.Length; 21 _index = 0; 22 } 23 public int Length 24 { 25 get { return _validLength; } 26 } 27 28 public void Remove(int data) 29 { 30 for (int i = 0; i < _validLength; i++) 31 { 32 if (_arr[i] == data) 33 { 34 for (int j = i; j < _validLength - 1; j++) 35 { 36 _arr[j] = _arr[j + 1]; 37 } 38 _validLength--; 39 //删除了一个记录,index向前移一位使current指向删除记录的前一个记录 40 _index = i - 1; 41 } 42 } 43 } 44 public void Reset() 45 { 46 _index = 0; 47 } 48 public bool MoveNext() 49 { 50 if (_index < _validLength - 1) 51 { 52 _index = _index + 1; 53 return true; 54 } 55 return false; 56 57 } 58 public int Current 59 { 60 get { return _arr[_index]; } 61 } 62 } 63 64 //以数组结构存储数据,Length为实际记录数,Remove一个元素后,其记录项的值设为0,Current为当前指向记录 65 public class SqArray2 : IMyEnumerator<int> 66 { 67 int[] _arr; 68 int _validDataNumber; 69 int _index; 70 71 public SqArray2(int[] arr) 72 { 73 _arr = new int[arr.Length]; 74 arr.CopyTo(_arr, 0); 75 _validDataNumber = _arr.Length; 76 _index = 0; 77 } 78 public int Length 79 { 80 get { return _validDataNumber; } 81 } 82 83 public void Remove(int data) 84 { 85 for (int i = 0; i < _arr.Length; i++) 86 { 87 if (_arr[i] == data) 88 { 89 _arr[i] = 0; 90 _validDataNumber--; 91 //因为当前记录被删了,这里需要设置_current,使它指向前一个有效记录 92 } 93 } 94 } 95 public bool MoveNext() 96 { 97 for (int loc = _index + 1; loc < _arr.Length; loc++) 98 { 99 if (_arr[loc] != 0) 100 { 101 _index = loc; 102 return true; 103 } 104 } 105 return false; 106 } 107 public void Reset() 108 { 109 for (int loc = 0; loc < _arr.Length; loc++) 110 { 111 if (_arr[loc] != 0) 112 { 113 _index = loc; 114 break; 115 } 116 } 117 } 118 public int Current 119 { 120 get 121 { 122 return _arr[_index]; 123 } 124 } 125 } 126 127 public class LNode 128 { 129 public LNode Next; 130 public int Value; 131 public LNode(int value) : this(value, null) { } 132 public LNode(int value, LNode next) 133 { 134 Next = next; 135 Value = value; 136 } 137 } 138 //带有头结点的链表结构 139 public class LinkList : IMyEnumerator<LNode> 140 { 141 142 143 private LNode _head, _tail; 144 private int _length; 145 private LNode _current; 146 147 public int Length 148 { 149 get { return _length; } 150 } 151 152 public LinkList() 153 { 154 _head = _tail = new LNode(-1); 155 } 156 public LinkList(int[] arr) 157 : this() 158 { 159 for (int i = 0; i < arr.Length; i++) 160 { 161 Add(arr[i]); 162 } 163 } 164 public void Add(int data) 165 { 166 _tail.Next = new LNode(data); 167 _tail = _tail.Next; 168 _length++; 169 } 170 public LNode Current 171 { 172 get 173 { 174 return _current; 175 } 176 } 177 public void Remove(LNode lNode) 178 { 179 if (_head == null) 180 throw new ArgumentOutOfRangeException(); 181 else 182 { 183 LNode p = _head; 184 while (p.Next != null) 185 { 186 if (p.Next.Value == lNode.Value) 187 { 188 _current = p; 189 p.Next = p.Next.Next; 190 _length--; 191 return; 192 } 193 p = p.Next; 194 } 195 196 } 197 } 198 public bool MoveNext() 199 { 200 if (_current.Next != null) 201 { 202 _current = Current.Next; 203 return true; 204 } 205 return false; 206 } 207 208 public void Reset() 209 { 210 _current = _head.Next; 211 } 212 }
客户端代码(包括测试数据和算法):
View Code
1 public class Program 2 { 3 public static void Main(string[] args) 4 { 5 //Black box testing (equivalence divsion,bounary value) 6 int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; 7 //arr = new int[] { 1, 2, 3, 4 }; //even number 8 //arr = new int[] { 1, 2, 3, 4, 5 }; //odd number 9 //arr = new int[] { 1, 3, 2, 4 }; //mix the ordering up 10 //arr = new int[] { 1, 2, 3, 5 }; //miss a number 11 12 //arr = null; //array is null 13 //arr = new int[] { -1 }; //number is negative number 14 //arr = new int[] { 0 }; //number is zero 15 //arr = new int[] { int.MaxValue}; //bounary test 16 //arr = new char[] { 'a',/0 }; //different type 17 18 19 SqArray1 myArr = new SqArray1(arr); 20 Suanfa(myArr); 21 Console.WriteLine(myArr.Current.ToString()); 22 23 Suanfa(myArr); 24 Console.WriteLine(myArr.Current.ToString()); 25 26 LinkList myList = new LinkList(arr); 27 Suanfa(myList); 28 Console.WriteLine(myList.Current.Value.ToString()); 29 Console.Read(); 30 } 31 32 public static void Suanfa<T>(IMyEnumerator<T> myList) 33 { 34 int count = 0; 35 while (myList.Length > 1) 36 { 37 myList.Reset(); 38 do 39 { 40 count++; 41 if (count % 2 == 0) 42 { 43 myList.Remove(myList.Current); 44 } 45 } 46 while (myList.MoveNext()); 47 } 48 myList.Reset(); 49 } 50 }