如果a[i]==currentValue,则计数器值加1。 如果a[i] != currentValue, 则计数器值减1,如果计数器值小于0,则更新当前值为a[i],并将计数器值重置为1。 复制代码 代码如下: // 找出数组中出现次数超过一半的元素 int Find(int* a, int n) { int curValue = a[0] ; int count = 1 ;
复制代码 代码如下: // 三个数组的共同元素-只找最小的 void FindCommonElements(int a[], int b[], int c[], int x, int y, int z) { for(int i = 0, j = 0, k = 0; i < x && j < y && k < z;) { if(a[i] < b[j]) { i++ ; } else // a[i] >= b[j] { if(b[j] < c[k]) { j++ ; } else // b[j] >= c[k] { if(c[k] < a[i]) { k++ ; } else // c[k] >= a[i] { cout << c[k] << endl ; return ; } } } }
cout << "Not found!" << endl ; }
如果三个数组都无序,可以先对a, b进行排序,然后对c中任意一个元素都在b和c中做二分搜索。 复制代码 代码如下: // Find the unique common element in 3 arrays // O(NlogN) int UniqueCommonItem(int *a, int *b, int *c, int n) { // sort array a qsort(a, n, sizeof(int), compare) ; // NlogN
// sort array b qsort(b, n, sizeof(int), compare) ; // NlogN
// for each element in array c, do a binary search in a and b // This is up to a complexity of N*2*logN for (int i = 0; i < n; i++) { if(BinarySearch(a, n, c[i]) && BinarySearch(b, n, c[i])) return c[i] ; }
return - 1 ; // not found }
也可以对a进行排序,然后对于b和c中任意一个元素都在a中进行二分搜索。 复制代码 代码如下: // Find the unique common element in 3 arrays // O(NlogN) int UniqueCommonItem1(int *a, int *b, int *c, int n) { // sort array a qsort(a, n, sizeof(int), compare) ; // NlogN
// Space for time bool *bb = new bool[n] ; memset(bb, 0, n) ;
bool *bc = new bool[n] ; memset(bb, 0, n) ;
// for each element in b, do a BS in a and mark all the common element for (int i = 0; i < n; i++) // NlogN { if(BinarySearch(a, n, b[i])) bb[i] = true ; }
// for each element in c, do a BS only if b[i] is true for (int i = 0; i < n; i++) // NlogN { if(b[i] && BinarySearch(a, n, c[i])) return c[i] ; }
return - 1 ; // not found }
排序和二分搜索代码如下: 复制代码 代码如下: // Determine whether a contains value k bool BinarySearch(int *a, int n, int k) { int left = 0 ; int right = n - 1 ; while (left <= right) { int mid = (left + right) ;
编程珠玑上的经典题目,不多说了。 复制代码 代码如下: // 子数组的最大和 int Sum(int* a, int n) { int curSum = 0; int maxSum = 0; for (int i = 0; i < n; i++) { if (curSum + a[i] < 0) curSum = 0; else { curSum += a[i] ; maxSum = max(maxSum, curSum); } } return maxSum; }
与最大子段和类似,注意处理负数的情况。 复制代码 代码如下: // 子数组的最大乘积 int MaxProduct(int *a, int n) { int maxProduct = 1; // max positive product at current position int minProduct = 1; // min negative product at current position int r = 1; // result, max multiplication totally
for (int i = 0; i < n; i++) { if (a[i] > 0) { maxProduct *= a[i]; minProduct = min(minProduct * a[i], 1); } else if (a[i] == 0) { maxProduct = 1; minProduct = 1; } else // a[i] < 0 { int temp = maxProduct; maxProduct = max(minProduct * a[i], 1); minProduct = temp * a[i]; }
比如数组 1 2 3 4循环右移1位 将变成 4 1 2 3, 观察可知1 2 3 的顺序在移位前后没有改变,只是和4的位置交换了一下,所以等同于1 2 3 4 先划分为两部分 1 2 3 | 4,然后将1 2 3逆序,再将4 逆序 得到 3 2 1 4,最后整体逆序 得到 4 1 2 3。 复制代码 代码如下: // 将buffer中start和end之间的元素逆序 void Reverse( int buffer[], int start, int end ) { while ( start < end ) { int temp = buffer[ start ] ; buffer[ start++ ] = buffer[ end ] ; buffer[ end-- ] = temp ; } }
// 将含有n个元素的数组buffer右移k位 void Shift( int buffer[], int n, int k ) { k %= n ;
Reverse( buffer, 0, n - k - 1) ; Reverse( buffer, n - k, n - 1 ) ; Reverse( buffer, 0, n - 1 ) ; }
字符串逆序 给定一个含有n个元素的字符数组a,将其原地逆序。
可能您觉得这不是关于数组的,而是关于字符串的。是的。但是别忘了题目要求的是原地逆序,也就是不允许额外分配空间,那么参数肯定是字符数组形式,因为字符串是不能被修改的(这里只C/C++中的字符串常量),所以,和数组有关了吧,只不过不是整型数组,而是字符数组。用两个指针分别指向字符数组的首位,交换其对应的字符,然后两个指针分别向数组中央移动,直到交叉。 复制代码 代码如下: // 字符串逆序 void Reverse(char *a, int n) { int left = 0; int right = n - 1;
典型的排列组合问题,首选回溯法,为了简化问题,我们将a中n个元素值分别设置为1-n。 复制代码 代码如下: // n选m的所有组合 int buffer[100] ;
void PrintArray(int *a, int n) { for (int i = 0; i < n; ++i) cout << a[i] << " "; cout << endl ; }
bool IsValid(int lastIndex, int value) { for (int i = 0; i < lastIndex; i++) { if (buffer[i] >= value) return false; } return true; }
void Select(int t, int n, int m) { if (t == m) PrintArray(buffer, m); else { for (int i = 1; i <= n; i++) { buffer[t] = i; if (IsValid(t, i)) Select(t + 1, n, m); } } }
a[i] a[i] == b[j],则c[k]等于a[i]或b[j]皆可。 a[i] > b[j],则c[k] = b[j]。 重复以上过程,直到i或者j到达数组末尾,然后将剩下的元素直接copy到数组c中即可。 复制代码 代码如下: // 合并两个有序数组 void Merge(int *a, int *b, int *c, int n) { int i = 0 ; int j = 0 ; int k = 0 ;
此排序非传统意义上的排序,因为它要求排序前后非0元素的相对位置不变,或许叫做整理会更恰当一些。我们可以从后向前遍历整个数组,遇到某个位置i上的元素是非0元素时,如果a[k]为0,则将a[i]赋值给a[k],a[k]赋值为0。实际上i是非0元素的下标,而k是0元素的下标。 复制代码 代码如下: void Arrange(int* a, int n) { int k = n - 1 ; for (int i = n - 1; i >= 0; --i) { if (a[i] != 0) { if (a[k] == 0) { a[k] = a[i] ; a[i] = 0 ; } --k ; } } }