Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2014
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.66 KB | None | 0 0
  1. public class FindKthMax_MOM {
  2. // Find Kth max by median of medians pivot method.
  3. // Time complexity, worst case = O(n).
  4. // n is the num of the elem in the given array.
  5. private static LNode <Integer> mergeSortLLForIntDataFromMinToMax (LNode <Integer> head) {
  6. if (head == null || head.next == null) return head;
  7. // Get the mid point of this linked list.
  8. LNode <Integer> preSlower = head;
  9. LNode <Integer> slower = head;
  10. LNode <Integer> faster = head;
  11. while (faster != null && faster.next != null) {
  12. preSlower = slower;
  13. slower = slower.next;
  14. faster = faster.next.next;
  15. }
  16. // Cut off this main linked list.
  17. preSlower.next = null;
  18.  
  19. // Do recursion on the left part and the right part.
  20. LNode <Integer> left = mergeSortLLForIntDataFromMinToMax(head);
  21. LNode <Integer> right = mergeSortLLForIntDataFromMinToMax(slower);
  22.  
  23. // Merge left part and the right part from min to max.
  24. LNode <Integer> currHead = new LNode <Integer> ();
  25. LNode <Integer> tempCurrHead = currHead;
  26. while (left != null && right != null) {
  27. if (left.data <= right.data) {
  28. // Add the elem of left part into the linked list.
  29. tempCurrHead.next = left;
  30. left = left.next;
  31. } else {
  32. // Add the elem of right part into the linked list.
  33. tempCurrHead.next = right;
  34. right = right.next;
  35. }
  36. tempCurrHead = tempCurrHead.next;
  37. }
  38. if (left != null) {
  39. // Add the remaining part of left part into the main linked list.
  40. tempCurrHead.next = left;
  41. left = left.next;
  42. tempCurrHead = tempCurrHead.next;
  43. } else if (right != null) {
  44. // Add the remaining part of right part into the main linked list.
  45. tempCurrHead.next = right;
  46. right = right.next;
  47. tempCurrHead = tempCurrHead.next;
  48. }
  49. return currHead.next;
  50. }
  51.  
  52. private static int partition_second (int[] givenArray, int start, int end, int pivotIndex) {
  53. int pivot = givenArray[pivotIndex];
  54. int left = start;
  55. int right = end;
  56. while (left <= right) {
  57. while (givenArray[left] < pivot) left ++;
  58. while (givenArray[right] > pivot) right --;
  59. if (left <= right) {
  60. // Exchange the givenArray[left] and the givenArray[right].
  61. exchange(givenArray, left, right);
  62. left ++;
  63. right --;
  64. }
  65. }
  66. return left;
  67. }
  68. private static void quickSortFromMinToMax (int[] givenArray, int start, int end) {
  69. if (start >= end) return;
  70. // Generate a random num in the range[start, end].
  71. int rand = start + (int)(Math.random() * ((end - start) + 1));
  72. // Use this random num as the pivot index to partition the given array in the current scope.
  73. int split = partition_second (givenArray, start, end, rand);
  74. // Do recursion.
  75. quickSortFromMinToMax(givenArray, start, split - 1);
  76. quickSortFromMinToMax(givenArray, split, end);
  77. }
  78. private static int getMedianFromLL (LNode <Integer> head) {
  79. if (head == null) return Integer.MIN_VALUE;
  80. // Get the mid point of this linked list.
  81. LNode <Integer> slower = head;
  82. LNode <Integer> faster = head;
  83. while (faster != null && faster.next != null) {
  84. slower = slower.next;
  85. faster = faster.next.next;
  86. }
  87. return slower.data;
  88. }
  89. private static int getMedian (int[] givenArray, int start, int end) {
  90. int size = end - start + 1;
  91.  
  92. int numOfSubSet = (float)(size) / 5 > (size / 5) ? (size / 5 + 1) : (size / 5);
  93.  
  94. if (numOfSubSet <= 1) {
  95. // Sort this little array, and return its median.
  96. quickSortFromMinToMax(givenArray, start, end);
  97. return givenArray[(start + end) / 2];
  98. }
  99. // Split this entire given array into subset.
  100. int givenArrayIndex = start;
  101. LList <LList<Integer>> mainLL = new LList <LList<Integer>> ();
  102. for (int i = 0; i < numOfSubSet; i ++) {
  103. // Use the linked list to store each sub set.
  104. LList <Integer> subLL = new LList <Integer> ();
  105.  
  106. // Load this subLL by the elems of givenArray.
  107. for (int j = 0; j < 5; j ++) {
  108. if (givenArrayIndex <= end) {
  109. subLL.addNode (givenArray[givenArrayIndex]);
  110. givenArrayIndex ++;
  111. } else break;
  112. }
  113. // Sort this linked list by merge sort.
  114. subLL.head = mergeSortLLForIntDataFromMinToMax(subLL.head);
  115. mainLL.addNode (subLL);
  116. }
  117. // Calculate each median for each subset.
  118. int[] medians = new int[numOfSubSet];
  119. int mediansIndex = 0;
  120. LNode <LList<Integer>> tempSubSet = mainLL.head;
  121. while (tempSubSet != null) {
  122. medians[mediansIndex] = getMedianFromLL (tempSubSet.data.head);
  123. mediansIndex ++;
  124. tempSubSet = tempSubSet.next;
  125. }
  126.  
  127. // Sort the medians array.
  128. quickSortFromMinToMax (medians, 0, numOfSubSet - 1);
  129.  
  130. // Return the median of medians.
  131. return medians[numOfSubSet / 2];
  132.  
  133. }
  134. private static void exchange (int[] givenArray, int firstIndex, int secondIndex) {
  135. int tempElem = givenArray[firstIndex];
  136. givenArray[firstIndex] = givenArray[secondIndex];
  137. givenArray[secondIndex] = tempElem;
  138. }
  139. private static int partition (int[] givenArray, int start, int end, int pivot) {
  140. int left = start;
  141. int right = end;
  142. while (left <= right) {
  143. while (givenArray[left] > pivot) left ++;
  144. while (givenArray[right] < pivot) right --;
  145. if (left <= right) {
  146. // Exchange the givenArray[left] and the givenArray[right].
  147. exchange(givenArray, left, right);
  148. left ++;
  149. right --;
  150. }
  151. }
  152. return left;
  153. }
  154. private static int findKthMax_MOM_Helper (int[] givenArray, int start, int end, int k) {
  155. if (start > end) return Integer.MIN_VALUE;
  156. // Get the median of the givenArray in the current scope.
  157. int median = getMedian (givenArray, start, end);
  158.  
  159. // Use this median as the pivot to partition the given array in the current scope.
  160. int split = partition (givenArray, start, end, median);
  161.  
  162. if (k == split) return givenArray[split - 1];
  163. else if (k < split) return findKthMax_MOM_Helper(givenArray, start, split - 1, k);
  164. else return findKthMax_MOM_Helper(givenArray, split, end, k);
  165. }
  166. public static int findKthMax_MOM (int[] givenArray, int k) {
  167. int size = givenArray.length;
  168. if (k < 1 || k > size) return Integer.MIN_VALUE;
  169. return findKthMax_MOM_Helper(givenArray, 0, size - 1, k);
  170. }
  171.  
  172. // Main method to test.
  173. public static void main (String[] args) {
  174. // Test data: {8, 5, 2, 0, 9, 1}.
  175. int[] givenArray = {8, 5, 2, 0, 9, 1};
  176.  
  177. // Test finding the Kth max by median of medians as pivot method.
  178. System.out.println("Test finding Kth max by median of medians as pivot method, rest = " + findKthMax_MOM(givenArray, 2));
  179. }
  180. }
  181.  
  182. private static int partition (int[] givenArray, int start, int end, int pivot) {
  183. int left = start;
  184. int right = end;
  185. while (left <= right) {
  186. while (givenArray[left] > pivot) left ++;
  187. while (givenArray[right] < pivot) right --;
  188. if (left <= right) {
  189. // Exchange the givenArray[left] and the givenArray[right].
  190. exchange(givenArray, left, right);
  191. left ++;
  192. right --;
  193. }
  194. }
  195. return left;
  196. }
  197.  
  198. private static int findKthMax_MOM_Helper (int[] givenArray, int start, int end, int k) {
  199. if (start > end) return Integer.MIN_VALUE;
  200. // Get the median of the givenArray in the current scope.
  201. int median = getMedian (givenArray, start, end);
  202.  
  203. // Use this median as the pivot to partition the given array in the current scope.
  204. int split = partition (givenArray, start, end, median);
  205.  
  206. if (k == split) return givenArray[split - 1];
  207. else if (k < split) return findKthMax_MOM_Helper(givenArray, start, split - 1, k);
  208. else return findKthMax_MOM_Helper(givenArray, split, end, k);
  209. }
  210.  
  211. private static int getMedian (int[] givenArray, int start, int end) {
  212. int size = end - start + 1;
  213.  
  214. int numOfSubSet = (float)(size) / 5 > (size / 5) ? (size / 5 + 1) : (size / 5);
  215.  
  216. if (numOfSubSet <= 1) {
  217. // Sort this little array, and return its median.
  218. quickSortFromMinToMax(givenArray, start, end);
  219. return givenArray[(start + end) / 2];
  220. }
  221. // Split this entire given array into subset.
  222. int givenArrayIndex = start;
  223. LList <LList<Integer>> mainLL = new LList <LList<Integer>> ();
  224. for (int i = 0; i < numOfSubSet; i ++) {
  225. // Use the linked list to store each sub set.
  226. LList <Integer> subLL = new LList <Integer> ();
  227.  
  228. // Load this subLL by the elems of givenArray.
  229. for (int j = 0; j < 5; j ++) {
  230. if (givenArrayIndex <= end) {
  231. subLL.addNode (givenArray[givenArrayIndex]);
  232. givenArrayIndex ++;
  233. } else break;
  234. }
  235. // Sort this linked list by merge sort.
  236. subLL.head = mergeSortLLForIntDataFromMinToMax(subLL.head);
  237. mainLL.addNode (subLL);
  238. }
  239. // Calculate each median for each subset.
  240. int[] medians = new int[numOfSubSet];
  241. int mediansIndex = 0;
  242. LNode <LList<Integer>> tempSubSet = mainLL.head;
  243. while (tempSubSet != null) {
  244. medians[mediansIndex] = getMedianFromLL (tempSubSet.data.head);
  245. mediansIndex ++;
  246. tempSubSet = tempSubSet.next;
  247. }
  248.  
  249. // Sort the medians array.
  250. quickSortFromMinToMax (medians, 0, numOfSubSet - 1);
  251.  
  252. // Return the median of medians.
  253. int median = medians[0];
  254. if (numOfSubSet > 2) median = numOfSubSet % 2 == 0 ? medians[numOfSubSet / 2 - 1] : medians[numOfSubSet / 2];
  255. return median;
  256. }
  257.  
  258. public class LList<T> {
  259. public LNode<T> head;
  260.  
  261. public void addNode(T i) {
  262. LNode<T> lNode = new LNode<>();
  263. lNode.data = i;
  264. lNode.next = head;
  265. head = lNode;
  266. }
  267.  
  268. //only for testing
  269. @Override
  270. public String toString() {
  271. LNode<T> node = head;
  272. StringBuilder sb = new StringBuilder();
  273. for (;node!=null;node=node.next){
  274. sb.append(node.data.toString());
  275. sb.append(",");
  276. }
  277. return sb.toString();
  278. }
  279. }
  280.  
  281. public class LNode<T> {
  282. LNode<T> next;
  283. T data;
  284. }
  285.  
  286. System.out.println("Test finding ..., rest = " + findKthMax_MOM(givenArray, 1));
  287. System.out.println("Test finding ..., rest = " + findKthMax_MOM(givenArray, 2));
  288. System.out.println("Test finding ..., rest = " + findKthMax_MOM(givenArray, 3));
  289. System.out.println("Test finding ..., rest = " + findKthMax_MOM(givenArray, 4));
  290. System.out.println("Test finding ..., rest = " + findKthMax_MOM(givenArray, 5));
  291. System.out.println("Test finding ..., rest = " + findKthMax_MOM(givenArray, 6));
  292.  
  293. Test finding ..., rest = 9
  294. Test finding ..., rest = 8
  295. Test finding ..., rest = 5
  296. Test finding ..., rest = 2
  297. Test finding ..., rest = 1
  298. Test finding ..., rest = 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement