28 数组中出现次数超过一半的数字
1 //数组中出现次数超过一半的数字 2 //数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。
由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 3 // 4 //常规思路1:先对这个数组进行排序,排序的时间复杂度为O(nlogn),然后进行遍历,进行查找。不建议使用这种方法; 5 6 7 //常规思路2:基于Partition函数的O(n)的算法 8 //如果对这个数组进行排序,那么排序之后位于数组中间的数字一定是那个出现次数超过数组长度一半的数字。
即这个数字就是统计学中的中位数。即长度为n的数组中第n/2大的数字。 9 //利用成熟的O(n)算法得到数组中任意第K大的数字--利用的快排思想 10 //快排思想:先在数组中随机选择一个数字,然后调整数组中数字的顺序,使得比选中的数字小数字都排在它前边,比选中数字大的数字都排在它后面。 11 //例如:如果这个选中的数字下标刚好是n/2,那么该数字就是数组中位数;如果它的下标大于n/2,
那么中位数应该位于它的左边,我们可以继续在它的左边中进行查找。如果他的下标小于n/2,
那么中位数应该在它的右边,接着在右边进行查找。 12 int Partition(int data[], int length, int start, int end) 13 { 14 if(data == NULL || length<=0 || start <= 0 || end <= 0) 15 { 16 return 0; 17 } 18 int index = RangdomInRange(start, end); 19 int pv = data[index];//选择最后一个结点为枢轴 20 Swap(&data[index], &data[start]); 21 while(start < end) 22 { 23 if ((start < end) && (data[end]> pv))//先从右边开始 24 { 25 end--; 26 } 27 Swap(&array[index], &array[end]); 28 if ((start < end) && (data[start])< pv) 29 { 30 start++; 31 } 32 Swap(&array[index], &array[start]); 33 } 34 return start; 35 } 36 void QuickSort(int data[], int length, int start, int end) 37 { 38 if (start == end) 39 { 40 return ; 41 } 42 int pivot = Partition(data, length, start, end); 43 QuickSort(data, length, start ,pivot-1); 44 QuickSort(data, length, pivot+1, end); 45 } 46 47 //---------------------解答题--------------- 48 class Solution { 49 public: 50 int MoreThanHalfNum_Solution(vector<int> numbers) 51 { 52 if (numbers.size() <= 0) 53 { 54 return 0; 55 } 56 //利用快排思想解决问题 57 int length = numbers.size()-1; 58 int middle = length>>1; 59 int start = 0; 60 int end = length -1; 61 int index = Partition(numbers, length, start, end);//上述快排参数类型是数组,此处是vector类型 62 while(index != middle) 63 { 64 if (index > middle) 65 { 66 end = index - 1; 67 index = Partition(numbers, length, start, end); 68 } 69 else 70 { 71 start = index +1; 72 index = Partition(numbers, length, start, end); 73 } 74 } 75 int result = numbers[middle]; 76 int times = 0;//计算累计次数 77 for (int i = 0; i < length; ++i) 78 { 79 if (numbers[i] == result) 80 { 81 times++; 82 } 83 84 } 85 if (times * 2 <= length) 86 { 87 return 0; 88 } 89 return result; 90 } 91 }; 92 93 //思路2:根据数组特点找出O(N)的算法。 94 //遍历数组的时候,保存2个值---一个是数组中的数字,一个是次数。当我们遍历到下一个数字的时候,
如果下一个数字和我们之前保存的数字相同,则次数加一;如果下一个数字和我们之前保存的数字不同,
则次数减1.如果次数为0,我们需要保存下一个数字,并将次数设为1; 95 class Solution { 96 public: 97 int MoreThanHalfNum_Solution(vector<int> numbers) 98 { 99 int length = numbers.size(); 100 if (length <= 0) 101 { 102 return 0; 103 } 104 int times = 1; 105 int result = numbers[0]; 106 for (int i = 1; i <= length-1; ++i) 107 { 108 if (0 == times) 109 { 110 result = numbers[i];//将次数多且累计次数的,存放起来,若最后次数还大于1,则就是要找的数字是最后将次数设置为1对应的数字 111 //eg:1 3 1 1 9 112 //最后一次将次数设置为1的是第三个数字1. 113 times = 1; 114 } 115 if (result == numbers[i]) 116 { 117 times++; 118 } 119 else 120 times--; 121 } 122 123 //还要判断输入的数字是否满足条件eg:[1,2,3,2,4,2,5,2,3] 124 int counts = 0;//计算累计次数 125 for (int i = 0; i < length; ++i) 126 { 127 if (numbers[i] == result) 128 { 129 counts++; 130 } 131 132 } 133 if (counts * 2 <= length) 134 { 135 return 0; 136 } 137 return result; 138 } 139 };
在代码的世界尽情的翱翔吧!