色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

php數(shù)組的一些常見操作匯總

數(shù)組求和
給定一個(gè)含有n個(gè)元素的整型數(shù)組a,求a中所有元素的和。可能您會(huì)覺得很簡(jiǎn)單,是的,的確簡(jiǎn)單,但是為什么還要說呢,原因有二,第一,這道題要求用遞歸法,只用一行代碼。第二,這是我人生中第一次面試時(shí)候遇到的題,意義特殊。

簡(jiǎn)單說一下,兩種情況:

如果數(shù)組元素個(gè)數(shù)為0,那么和為0。
如果數(shù)組元素個(gè)數(shù)為n,那么先求出前n - 1個(gè)元素之和,再加上a[n - 1]即可。
復(fù)制代碼 代碼如下:
// 數(shù)組求和
int sum(int *a, int n)
{
return n == 0 ? 0 : sum(a, n - 1) + a[n - 1];
}

求數(shù)組的最大值和最小值
給定一個(gè)含有n個(gè)元素的整型數(shù)組a,找出其中的最大值和最小值。

常規(guī)的做法是遍歷一次,分別求出最大值和最小值,但我這里要說的是分治法(Divide and couquer),將數(shù)組分成左右兩部分,先求出左半部份的最大值和最小值,再求出右半部份的最大值和最小值,然后綜合起來求總體的最大值及最小值。這是個(gè)遞歸過程,對(duì)于劃分后的左右兩部分,同樣重復(fù)這個(gè)過程,直到劃分區(qū)間內(nèi)只剩一個(gè)元素或者兩個(gè)元素。
復(fù)制代碼 代碼如下:
// 求數(shù)組的最大值和最小值,返回值在maxValue和minValue
void MaxandMin(int *a, int l, int r, int& maxValue, int& minValue)
{
if(l == r) // l與r之間只有一個(gè)元素
{
maxValue = a[l] ;
minValue = a[l] ;
return ;
}

if(l + 1 == r) // l與r之間只有兩個(gè)元素
{
if(a[l] >= a[r])
{
maxValue = a[l] ;
minValue = a[r] ;
}
else
{
maxValue = a[r] ;
minValue = a[l] ;
}
return ;
}

int m = (l + r) / 2 ; // 求中點(diǎn)

int lmax ; // 左半部份最大值
int lmin ; // 左半部份最小值
MaxandMin(a, l, m, lmax, lmin) ; // 遞歸計(jì)算左半部份

int rmax ; // 右半部份最大值
int rmin ; // 右半部份最小值
MaxandMin(a, m + 1, r, rmax, rmin) ; // 遞歸計(jì)算右半部份

maxValue = max(lmax, rmax) ; // 總的最大值
minValue = min(lmin, rmin) ; // 總的最小值
}


求數(shù)組的最大值和次大值
給定一個(gè)含有n個(gè)元素的整型數(shù)組,求其最大值和次大值。

思想和上一題類似,同樣是用分治法,不多說了,直接看代碼:

復(fù)制代碼 代碼如下:
// 求數(shù)組的最大值和次大值,返回值在max和second中
void MaxandMin(int *a, int left, int right, int &max, int &second)
{
if(left == right)
{
max = a[left] ;
second = a[left] ;
}
else if(left + 1 == right)
{
max = a[left] > a[right] ? a[left] : a[right] ;
second = a[left] < a[right] ? a[left] : a[right] ;
}
else
{
int mid = left + (right - left) / 2 ;

int leftmax ;
int leftmin ;
MaxandMin(a, left, mid, leftmax, leftmin) ;

int rightmax ;
int rightmin ;
MaxandMin(a, mid + 1, right, rightmax, rightmin) ;

max = leftmax > rightmax ? leftmax : rightmax ;
second = leftmax < rightmax ? leftmax : rightmax ;
}
}


求數(shù)組中出現(xiàn)次數(shù)超過一半的元素
給定一個(gè)n個(gè)整型元素的數(shù)組a,其中有一個(gè)元素出現(xiàn)次數(shù)超過n / 2,求這個(gè)元素。據(jù)說是百度的一道面試題。

設(shè)置一個(gè)當(dāng)前值和當(dāng)前值的計(jì)數(shù)器,初始化當(dāng)前值為數(shù)組首元素,計(jì)數(shù)器值為1,然后從第二個(gè)元素開始遍歷整個(gè)數(shù)組,對(duì)于每個(gè)被遍歷到的值a[i]。

如果a[i]==currentValue,則計(jì)數(shù)器值加1。
如果a[i] != currentValue, 則計(jì)數(shù)器值減1,如果計(jì)數(shù)器值小于0,則更新當(dāng)前值為a[i],并將計(jì)數(shù)器值重置為1。
復(fù)制代碼 代碼如下:
// 找出數(shù)組中出現(xiàn)次數(shù)超過一半的元素
int Find(int* a, int n)
{
int curValue = a[0] ;
int count = 1 ;

for (int i = 1; i

另一個(gè)方法是先對(duì)數(shù)組排序,然后取中間元素即可,因?yàn)槿绻硞€(gè)元素的個(gè)數(shù)超過一半,那么數(shù)組排序后該元素必定占據(jù)數(shù)組的中間位置。

求數(shù)組中元素的最短距離
給定一個(gè)含有n個(gè)元素的整型數(shù)組,找出數(shù)組中的兩個(gè)元素x和y使得abs(x - y)值最小。

先對(duì)數(shù)組排序,然后遍歷一次即可:

復(fù)制代碼 代碼如下:
int compare(const void* a, const void* b)
{
return *(int*)a - *(int*)b ;
}

void MinimumDistance(int* a, int n)
{
// Sort
qsort(a, n, sizeof(int), compare) ;

int i ; // Index of number 1
int j ; // Index of number 2

int minDistance = numeric_limits<int>::max() ;
for (int k = 0; k < n - 1; ++k)
{
if (a[k + 1] - a[k] < minDistance)
{
minDistance = a[k + 1] - a[k] ;
i = a[k] ;
j = a[k + 1] ;
}
}

cout << "Minimum distance is: " << minDistance << endl ;
cout << "i = " << i << " j = " << j << endl ;
}


求兩個(gè)有序數(shù)組的共同元素
給定兩個(gè)含有n個(gè)元素的有序(非降序)整型數(shù)組a和b,求出其共同元素,比如:a = 0, 1, 2, 3, 4和b = 1, 3, 5, 7, 9,輸出 1, 3。

充分利用數(shù)組有序的性質(zhì),用兩個(gè)指針i和j分別指向a和b,比較a[i]和b[j],根據(jù)比較結(jié)果移動(dòng)指針,則有如下三種情況:

a[i] < b[j],則i增加1,繼續(xù)比較
a[i] == b[j],則i和j皆加1,繼續(xù)比較
a[i]
重復(fù)以上過程直到i或j到達(dá)數(shù)組末尾。

復(fù)制代碼 代碼如下:
// 找出兩個(gè)數(shù)組的共同元素
void FindCommon(int* a, int* b, int n)
{
int i = 0;
int j = 0 ;

while (i < n && j < n)
{
if (a[i] < b[j])
++i ;
else if(a[i] == b[j])
{
cout << a[i] << endl ;
++i ;
++j ;
}
else// a[i] > b[j]
++j ;
}
}


這到題還有其他的解法,比如對(duì)于a中任意一個(gè)元素,在b中對(duì)其進(jìn)行Binary Search,因?yàn)閍中有n個(gè)元素,而在b中進(jìn)行Binary Search需要logn。所以找出全部相同元素的時(shí)間復(fù)雜度是O(nlogn)。

另外,上面的方法,只要b有序即可,a是否有序無所謂,因?yàn)槲覀冎皇窃赽中做Binary Search。如果a也有序的話,那么再用上面的方法就有點(diǎn)慢了,因?yàn)槿绻鸻中某個(gè)元素在b中的位置是k的話,那么a中下一個(gè)元素在b中的位置一定位于k的右側(cè),所以本次的搜索空間可以根據(jù)上次的搜索結(jié)果縮小,而不是仍然在整個(gè)b中搜索。也即如果a和b都有序的話,代碼可以做如下修改,記錄上次搜索時(shí)b中元素的位置,作為下一次搜索的起始點(diǎn)。

求三個(gè)數(shù)組的共同元素
給定三個(gè)含有n個(gè)元素的整型數(shù)組a,b和c,求他們最小的共同元素。

如果三個(gè)數(shù)組都有序,那么可以設(shè)置三個(gè)指針指向三個(gè)數(shù)組的頭部,然后根據(jù)這三個(gè)指針?biāo)傅闹颠M(jìn)行比較來移動(dòng)指針,直道找到共同元素。

復(fù)制代碼 代碼如下:
// 三個(gè)數(shù)組的共同元素-只找最小的
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 ;
}


如果三個(gè)數(shù)組都無序,可以先對(duì)a, b進(jìn)行排序,然后對(duì)c中任意一個(gè)元素都在b和c中做二分搜索。
復(fù)制代碼 代碼如下:
// 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
}

也可以對(duì)a進(jìn)行排序,然后對(duì)于b和c中任意一個(gè)元素都在a中進(jìn)行二分搜索。
復(fù)制代碼 代碼如下:
// 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
}

排序和二分搜索代碼如下:
復(fù)制代碼 代碼如下:
// 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) ;

if(a[mid] < k)
left = mid + 1 ;
if(a[mid] == k)
return true ;
else
right = mid - 1 ;
}

return false ;
}

// Compare function for qsort
int compare(const void* a, const void* b)
{
return *(int*)a - *(int*)b ;
}

總結(jié)一下,對(duì)于在數(shù)組中進(jìn)行查找的問題,可以分如下兩種情況處理:

如果給定的數(shù)組有序,那么首先應(yīng)該想到Binary Search,所需O(logn)。
如果給定的數(shù)組無序,那么首先應(yīng)該想到對(duì)數(shù)組進(jìn)行排序,很多排序算法都能在O(nlogn)時(shí)間內(nèi)對(duì)數(shù)組進(jìn)行排序,然后再使用二分搜索,總的時(shí)間復(fù)雜度仍是O(nlogn)。
如果能做到以上兩點(diǎn),大多數(shù)關(guān)于數(shù)組的查找問題,都能迎刃而解。

找出數(shù)組中唯一的重復(fù)元素
給定含有1001個(gè)元素的數(shù)組,其中存放了1-1000之內(nèi)的整數(shù),只有一個(gè)整數(shù)是重復(fù)的,請(qǐng)找出這個(gè)數(shù)。

求出整個(gè)數(shù)組的和,再減去1-1000的和即可,代碼略。

找出出現(xiàn)奇數(shù)次的元素
給定一個(gè)含有n個(gè)元素的整型數(shù)組a,其中只有一個(gè)元素出現(xiàn)奇數(shù)次,找出這個(gè)元素。

因?yàn)閷?duì)于任意一個(gè)數(shù)k,有k ^ k = 0,k ^ 0 = k,所以將a中所有元素進(jìn)行異或,那么個(gè)數(shù)為偶數(shù)的元素異或后都變成了0,只留下了個(gè)數(shù)為奇數(shù)的那個(gè)元素。

int FindElementWithOddCount(int *a, int n)
{
int r = a[0] ;

for (int i = 1; i
求數(shù)組中滿足給定和的數(shù)對(duì)
給定兩個(gè)有序整型數(shù)組a和b,各有n個(gè)元素,求兩個(gè)數(shù)組中滿足給定和的數(shù)對(duì),即對(duì)a中元素i和b中元素j,滿足i + j = d(d已知)。

兩個(gè)指針i和j分別指向數(shù)組的首尾,然后從兩端同時(shí)向中間遍歷,直到兩個(gè)指針交叉。
復(fù)制代碼 代碼如下:
// 找出滿足給定和的數(shù)對(duì)
void FixedSum(int* a, int* b, int n, int d)
{
for (int i = 0, j = n - 1; i < n && j >= 0)
{
if (a[i] + b[j] < d)
++i ;
else if (a[i] + b[j] == d)
{
cout << a[i] << ", " << b[j] << endl ;
++i ;
--j ;
}
else // a[i] + b[j] > d
--j ;
}
}

最大子段和
給定一個(gè)整型數(shù)組a,求出最大連續(xù)子段之和,如果和為負(fù)數(shù),則按0計(jì)算,比如1, 2, -5, 6, 8則輸出6 + 8 = 14。

編程珠璣上的經(jīng)典題目,不多說了。
復(fù)制代碼 代碼如下:
// 子數(shù)組的最大和
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;
}

最大子段積
給定一個(gè)整型數(shù)足a,求出最大連續(xù)子段的乘積,比如 1, 2, -8, 12, 7則輸出12 * 7 = 84。

與最大子段和類似,注意處理負(fù)數(shù)的情況。
復(fù)制代碼 代碼如下:
// 子數(shù)組的最大乘積
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];
}

r = max(r, maxProduct);
}

return r;
}

數(shù)組循環(huán)移位
將一個(gè)含有n個(gè)元素的數(shù)組向右循環(huán)移動(dòng)k位,要求時(shí)間復(fù)雜度是O(n),且只能使用兩個(gè)額外的變量,這是在微軟的編程之美上看到的一道題。

比如數(shù)組 1 2 3 4循環(huán)右移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。
復(fù)制代碼 代碼如下:
// 將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個(gè)元素的數(shù)組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 ) ;
}

字符串逆序
給定一個(gè)含有n個(gè)元素的字符數(shù)組a,將其原地逆序。

可能您覺得這不是關(guān)于數(shù)組的,而是關(guān)于字符串的。是的。但是別忘了題目要求的是原地逆序,也就是不允許額外分配空間,那么參數(shù)肯定是字符數(shù)組形式,因?yàn)樽址遣荒鼙恍薷牡模ㄟ@里只C/C++中的字符串常量),所以,和數(shù)組有關(guān)了吧,只不過不是整型數(shù)組,而是字符數(shù)組。用兩個(gè)指針分別指向字符數(shù)組的首位,交換其對(duì)應(yīng)的字符,然后兩個(gè)指針分別向數(shù)組中央移動(dòng),直到交叉。
復(fù)制代碼 代碼如下:
// 字符串逆序
void Reverse(char *a, int n)
{
int left = 0;
int right = n - 1;

while (left < right)
{
char temp = a[left] ;
a[left++] = a[right] ;
a[right--] = temp ;
}
}

組合問題
給定一個(gè)含有n個(gè)元素的整型數(shù)組a,從中任取m個(gè)元素,求所有組合。比如下面的例子:

a = 1, 2, 3, 4, 5
m = 3

輸出:

1 2 3, 1 2 4, 1 2 5, 1 3 4, 1 3 5, 1 4 5
2 3 4, 2 3 5, 2 4 5
3 4 5

典型的排列組合問題,首選回溯法,為了簡(jiǎn)化問題,我們將a中n個(gè)元素值分別設(shè)置為1-n。
復(fù)制代碼 代碼如下:
// 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);
}
}
}

合并兩個(gè)數(shù)組
給定含有n個(gè)元素的兩個(gè)有序(非降序)整型數(shù)組a和b。合并兩個(gè)數(shù)組中的元素到整型數(shù)組c,要求去除重復(fù)元素并保持c有序(非降序)。例子如下:

a = 1, 2, 4, 8
b = 1, 3, 5, 8
c = 1, 2, 3, 4, 5, 8

利用合并排序的思想,兩個(gè)指針i,j和k分別指向數(shù)組a和b,然后比較兩個(gè)指針對(duì)應(yīng)元素的大小,有以下三種情況:

a[i]
a[i] == b[j],則c[k]等于a[i]或b[j]皆可。
a[i] > b[j],則c[k] = b[j]。
重復(fù)以上過程,直到i或者j到達(dá)數(shù)組末尾,然后將剩下的元素直接copy到數(shù)組c中即可。
復(fù)制代碼 代碼如下:
// 合并兩個(gè)有序數(shù)組
void Merge(int *a, int *b, int *c, int n)
{
int i = 0 ;
int j = 0 ;
int k = 0 ;

while (i < n && j < n)
{
if (a[i] < b[j])// 如果a的元素小,則插入a中元素到c
{
c[k++] = a[i] ;
++i ;
}
else if (a[i] == b[j])// 如果a和b元素相等,則插入二者皆可,這里插入a
{
c[k++] = a[i] ;
++i ;
++j ;
}
else // a[i] > b[j] // 如果b中元素小,則插入b中元素到c
{
c[k++] = b[j] ;
++j ;
}
}

if (i == n) // 若a遍歷完畢,處理b中剩下的元素
{
for (int m = j; m < n; ++m)
c[k++] = b[m] ;
}
else//j == n, 若b遍歷完畢,處理a中剩下的元素
{
for (int m = i; m < n; ++m)
c[k++] = a[m] ;
}
}

重排問題
給定含有n個(gè)元素的整型數(shù)組a,其中包括0元素和非0元素,對(duì)數(shù)組進(jìn)行排序,要求:

排序后所有0元素在前,所有非零元素在后,且非零元素排序前后相對(duì)位置不變。
不能使用額外存儲(chǔ)空間。
例子如下:輸入 0, 3, 0, 2, 1, 0, 0,輸出 0, 0, 0, 0, 3, 2, 1。

此排序非傳統(tǒng)意義上的排序,因?yàn)樗笈判蚯昂蠓?元素的相對(duì)位置不變,或許叫做整理會(huì)更恰當(dāng)一些。我們可以從后向前遍歷整個(gè)數(shù)組,遇到某個(gè)位置i上的元素是非0元素時(shí),如果a[k]為0,則將a[i]賦值給a[k],a[k]賦值為0。實(shí)際上i是非0元素的下標(biāo),而k是0元素的下標(biāo)。
復(fù)制代碼 代碼如下:
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 ;
}
}
}

php技術(shù)php數(shù)組的一些常見操作匯總,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 南京市| 辽中县| 闽清县| 墨江| 应城市| 金湖县| 贡嘎县| 海盐县| 芜湖市| 温州市| 南康市| 蚌埠市| 定襄县| 鹿泉市| 江口县| 宁强县| 驻马店市| 盘山县| 广西| 祥云县| 四川省| 竹溪县| 鹿泉市| 肇庆市| 乌拉特中旗| 肃北| 大城县| 中宁县| 余干县| 台前县| 台北市| 宁都县| 横峰县| 广平县| 湛江市| 涿鹿县| 海兴县| 都兰县| 东乡县| 左云县| 溆浦县|