29. 数组中出现次数超过一半的数字.
方法a. 排序取中 O(nlogn).
方法b. partition 函数分割找中位数 >=O(n).
方法c. 设计数变量,扫描一遍。 O(n).
#include <stdio.h> int getNumber(int data[], int length){ /* if(checkInvalidArray(data, length)) return 0; */ int count = 1, value = data[0]; for(int i = 1; i < length; ++i) { if(count == 0){ value = data[i]; }else if(data[i] == value){ ++count; }else --count; } return value; } int main(){ int numbers[] = {2, 2, 2, 2, 6, 6, 6, 6, 6}; int value = getNumber(numbers, sizeof(numbers) / 4); /* if(value != 0 || !checkInvalidArray(data, length)) */ printf("%d ", value); return 0; }
30. 最小的 k 个数
a. partition 函数找到第 k 个数. >=O(n)
#include <stdio.h> int partition(int data[], int low, int high){ int value = data[low]; while(low < high){ while(low < high && data[high] >= value) --high; data[low] = data[high]; while(low < high && data[low] <= value) ++low; data[high] = data[low]; } data[low] = value; return low; } void getKNumber(int input[], int length, int out[], int k){ if(!input || !out || length < 1 || k > length || k < 1) return; int low = 0, high = length - 1, index; do{ index = partition(input, low, high); if(index < k-1) low = index + 1; else if(index > k-1) high = index - 1; }while(index != k-1); for(int i = 0; i < k; ++i) out[i] = input[i]; } int main(){ int numbers[10] = {3, 5, 2, 6, 7, 4, 9, 1, 2, 6}; int k = 5; getKNumber(numbers, 10, numbers, k); for(int i = 0; i < k; ++i) printf("%-3d", numbers[i]); printf(" "); return 0; }
b. 构造k 个元素的大顶堆
#include <stdio.h> void HeapAdjust(int data[], int endIndex, int father){ if(!data || endIndex < 0 || father > endIndex || father < 0) return; int value = data[father]; // set data[0] to save the value of original father for(int child = 2*father+1; child <= endIndex; child = 2*father+1){ if(child < endIndex && data[child] < data[child+1]) ++child; if(data[child] < value) break; else data[father] = data[child]; father = child; } data[father] = value; } void getKNumber(int input[], int length, int out[], int k){ if(!input || !out || length < 1 || k > length || k < 1) return; for(int i = 0; i < k; ++i) out[i] = input[i]; for(int i = k/2-1; i >= 0; --i) HeapAdjust(out, k-1, i); for(int i = k; i < length; ++i){ if(input[i] < out[0]){ out[0] = input[i]; HeapAdjust(out, k-1, 0); } } } int main(){ int numbers[10] = {3, 5, 2, 6, 7, 4, 9, 1, 2, 6}; enum{ k = 1}; int out[k+1] = {0}; getKNumber(numbers, 10, out, k); for(int i = k-1; i >= 0; --i){ int tem = out[i]; out[i] = out[0]; out[0] = tem; printf("%-3d", out[i]); HeapAdjust(out, i-1, 0); // DESC } printf(" "); return 0; }
31. 连续子数组的最大和
#include <stdio.h> bool Invalid_Input = false; int getKNumber(int data[], int length){ Invalid_Input = false; if(data == NULL || length < 1) { Invalid_Input = true; return 0; } int maxSum = 0x80000000; int curSum = 0; for(int i = 0; i < length; ++i){ if(curSum < 0) curSum = data[i]; else curSum += data[i]; if(curSum > maxSum) maxSum = curSum; } return maxSum; } int main(){ int numbers[] = {1,-2, 3, 10, -4, 7, 2, -5, -2, 4, -5, 4}; int maxSum = getKNumber(numbers, sizeof(numbers)/4); if(!Invalid_Input) printf("%d ", maxSum); return 0; }