筆試整理系列之數組篇(不斷更新)

1.問,如下代碼在x86平臺下輸出啥?html

int main(void) 
{     
    int a[4] = {1, 2, 3, 4};

    int *ptr1=(int *)(&a+1);      
    int *ptr2=(int *)((int)a+1);
      
    printf("%x, %x\n", ptr1[-1], *ptr2);      
    return 0;  
}

解答:00000004,02000000編程

2.http://www.cnblogs.com/graphics/archive/2010/08/24/1761620.html 來自於此博客的一些題目,代碼不是抄過來的,是本身實現。數組

  (1)給定一個含有n個元素的整型數組a,求a中全部元素的和。這道題要求用遞歸法,只用一行代碼。ui

    解答:
spa

int sum(int*a,int n)
{
   return (n-1==0)?a[n-1]:(a[n-1] + sum(a,n-1)); 
}

    (2)給定一個含有n個元素的整型數組a,找出其中的最大值和最小值.code

     解答:     htm

void MaxandMin(int *a,int n,int *max,int *min)
{
	int max1,min1;
	
	if(n == 1)
	{
		*max = *min = a[n-1];
		return;
	}
	else if(n == 2)
	{
		if(a[n-1] >= a[n-2])
		{
			*max = a[n-1];
			*min = a[n-2];
		}
		else
		{
			*max = a[n-1];
			*min = a[n-2];
		}
		return;
	}
	else
	{
		MaxandMin(a,n/2,&max1,&min1);
		*max = max1;*min = min1;
		MaxandMin(a+n/2,n-n/2,&max1,&min1);
		*max = (*max > max1)?(*max):max1;
		*min = (*min < min1)?(*min):min1;
	}
	return;
}

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

解答:(該解答在遇到 1 2 2 3 3 3這樣的數組時,返回3,3而不是3,2)排序

#include <stdio.h>

void MaxTwo(int *a, int n, int *max, int *max2)
{
	if(n == 1) 
	{
		*max = a[n-1];
                *max2 = INT_MIN;
		return;
	}
	else if(n == 2)
	{
		*max = (a[n-1]>a[n-2])?a[n-1]:a[n-2];
		*max2 = a[n-1]+a[n-2]-*max;
		return;
	}

	int max1 = 0,max21 = 0;

	MaxTwo(a,n/2,&max1,&max21);
	*max = max1;*max2 = max21;

	MaxTwo(a+n/2,n-n/2,&max1,&max21);
	*max = (*max > max1)?(*max):max1;
	if(*max != max1)
		*max2 = (*max2> max1)?(*max2):max1;
	else
		*max2 = (*max2> max21)?(*max2):max21;

	return;
}

int main()
{
	int a[7] = {1,2,3,4,9,6,7};
	int max,max2;

	MaxTwo(a,7,&max,&max2);
	
	printf("max = %d,max2 = %d\n",max,max2);
}


(4) 給定一個n個整型元素的數組a,其中有一個元素出現次數超過n / 2,求這個元素。聽說是百度的一道題。遞歸

  該題目相似於編程之美上尋找發帖水王,最直接的辦法是對數組排序,該元素必然會出如今數

組中間位置。

不採用排序的方法,按照編程之美所介紹,能夠每次刪掉兩個不一樣元素,刪到最後剩下的必定

是該出現次數超過一半的元素。(每次刪掉兩個不一樣元素,極限狀況即便每次都刪掉一個該元素,

因爲其超過一半,最後也必定會剩下)。代碼以下:

#include <stdio.h>

int Find(int *s, int N)
{
	int candidate;
	int ntimes,i;

	for(i = ntimes = 0 ; i < N; i++)
	{
		if(ntimes == 0)
		{
			candidate = s[i];
			ntimes = 1;
		}
		else 
		{
			if(candidate != s[i])
				ntimes--;
			else
				ntimes++;
		}
	}

	return candidate;
}

int main()
{
	int s[7] = {1,1,3,3,3,3,4};
	printf("%d \n",Find(s,7));
}


(5)給定一個含有n個元素的整型數組,找出數組中的兩個元素x和y使得abs(x - y)值最小。

先對數組排序,再遍歷一遍:

#include <stdio.h>

void QuickSort(int *s,int N)
{
	if(N <= 1) return ;
	if(N == 2)
	{
		if(s[0] > s[1])
		{
			s[0] = s[0]+s[1];
			s[1] = s[0]-s[1];
			s[0] = s[0]-s[1];
		}
		return;
	}

	int num = 0;
	int max,min,m = N/2;
	
	max = (s[m]>=s[N-1]?m:N-1);
	min = (s[m]<=s[N-1]?m:N-1);
	if(s[num] >= s[max])
		num = max;
	else if(s[num] < s[min])
		num = min;
	if(num != N-1)
	{
		s[num] = s[num] + s[N-1];
		s[N-1] = s[num] - s[N-1];
		s[num] = s[num] - s[N-1];
		num = N-1;
	}

	int i = 0,j = N-2;
	for(; i<j; )
	{
		if(s[i] < s[num])
			i++;
		if(s[j] >= s[num])
			j--;
		if( (s[i]>=s[num]) && (s[j]<s[num]) )
		{
			s[i] = s[i] + s[j];
			s[j] = s[i] - s[j];
			s[i] = s[i] - s[j];
			i++;j--;
		}
	}	
	if(s[i] < s[num])
		i++;
	s[num] = s[num] + s[i];
	s[i]   = s[num] - s[i];
	s[num] = s[num] - s[i];
	num = i;
	
	
	QuickSort(s,num);
	QuickSort(s+num+1,N-1-num);

}

int Find(int *s, int N)
{
	if(N < 1) return;

	QuickSort(s,N);

	int i = 1;
	
	int min = s[1] - s[0];

	for(;i < N; i++)
	{
		int tmp = abs(s[i]-s[i-1]);
		min = (tmp < min)?tmp:min;
	}
	return min;
}

int main()
{
	int a[7] = {9,3,7,8,2,1,4};
	printf("%d\n",Find(a,7));
}

(6)給定兩個含有n個元素的有序(非降序)整型數組a和b,求出其共同元素,好比

a = 0, 1, 2, 3, 4

b = 1, 3, 5, 7, 9

輸出 1, 3

#include <stdio.h>

void Find(int *a,int *b,int an, int bn)
{
	int i,j;
	for(i = 0,j =0; ((i<an)&&(j<bn)); )
	{
		if(a[i] < b[j])
			i++;
		else if(a[i] == b[j])
		{
			printf("%d,",a[i]);
			i++;j++;
		}
		else
			j++;
	}

}

int main()
{
	int a[5] = {0,1,2,3,4};
	int b[5] = {1,3,5,7,9};
	Find(a,b,5,5);	
}

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

解答:採用排序和二分搜索

(8)給定含有1001個元素的數組,其中存放了1-1000以內的整數,只有一個整數是重複的,請找出這個數。

解答:求出這1001個元素的和,而後減去1-1000的整數的和。 

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

由於對於任意一個數k,有k ^ k = 0,k ^ 0 = k,因此將a中全部元素進行異或,那麼個數爲偶數的元素異或後都變成了0,只留下了個數爲奇數的那個元素。

#include <stdio.h>


int Find(int *s, int n)
{
	int r=0,i;
	for(i = 0; i < n; i++)
		r = r^s[i];
	return r;
}
int main()
{
	int a[15] = {1,2,3,4,5,6,7,9,7,5,6,4,3,1,2};
	printf("%d\n",Find(a,15));
}

(10) 給定兩個有序整型數組a和b,各有n個元素,求兩個數組中知足給定和的數對,即對a中元素i和b中元素j,知足i + j = d(d已知)

(11)給定一個含有n個元素的整型數組a,從中任取m個元素,求全部組合。好比下面的例子

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

解答:



3.這幾天老是遇到的一個題目,求數組的子序列的最大和和最大積問題。

(1)求子數組最大和。

解答:對於數組A,其要求子序列爲如下三種狀況:

<1>A[0]就是最大和子序列;

<2>A[0]是最大和序列的一個元素;

<3>A[0]不是最大和子序列的元素。

設A[i...j]的最大和子序列爲ALL[i],包含A[i]的最大和子序列爲S[i],S[i] = max()則A[0..N]的最大和子序列能夠定義爲

max(S[i],ALL[i]);

顯然咱們能夠從最後一個元素向前搜索,得出最大和子序列,複雜度爲O(N)。

#include <stdio.h>

int max(int a, int b)
{
	return a>b ? a : b;
}
int Find(int *A, int N)
{
	int i;
	int ALL,S;

	ALL = A[N-1];
	S = A[N-1];
	for(i = N-2; i >= 0; i--)
	{
		S = max(A[i],A[i]+S);
		ALL = max(S,ALL);
	}

	return ALL;
}

int main()
{
	int a[6] = {1,-2,3,5,-3,2};
	printf("%d\n",Find(a,6));
}

(2)尋找子序列的最大積。麻煩之處在於有負數的狀況。

定義兩個值,max和min;max表明當前遍歷的子序列的最大值,遇到某個數,這個數使乘積爲負數和0時,將max置爲1;當遇到負數時,當前乘積若爲負數,將這個負數賦值給min,這樣再次遇到負數時,min乘以這個負數,若變爲正數,就將其賦值給max。

中秋節無聊思及下面代碼,忽然想到出現0,0,-1,0,0或全0這樣的序列,以下代碼仍是返回1.

#include <stdio.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))

int Find(int *s,int n)
{
	
	int max = 1,min = 1;
	int i,r=1;

	for(i = 0; i < n; i++)
	{
		if(s[i] > 0)
		{
			max = max*s[i];
			min = Min(min*s[i],1);
		}
		else if(s[i] == 0)
		{
			max = 1;
			min = 1;
		}
		else
		{
			int tmp = max;
			max = Max(min*s[i],1);
			min = Min(tmp*s[i],1);
		}
		r = Max(r,max);
	}
	return r;
}

int main()
{
	int a[7] = {1,2,0,-2,12,7,-1};
	printf("%d\n",Find(a,7));
}

修改後的代碼以下:

#include <stdio.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))

int Find(int *s,int n)
{
	
	int max = 1,min = 1;
	int i,r=1;
        int zero_num = 0, neg_num = 0;

	for(i = 0; i < n; i++)
	{
		if(s[i] > 0)
		{
			max = max*s[i];
			min = Min(min*s[i],1);
		}
		else if(s[i] == 0)
		{
			max = 1;
			min = 1;
                        zero_num++;
		}
		else
		{
			int tmp = max;
			max = Max(min*s[i],1);
			min = Min(tmp*s[i],1);
                        neg_num++;
		}
		r = Max(r,max);
	}

        if(neg_num+zero_num == N)
        {
                for(i = 2; i < N-1; i--)
                {
                        if((s[i]*s[i-1])||(s[i]*s[i+1]))return r;
                }
                return 0;
        }
	return r;
}

int main()
{
	int a[7] = {1,2,0,-2,12,7,-1};
	printf("%d\n",Find(a,7));
}

仍是求最大積的問題,前天小*科技筆試最後一題,不一樣的是數組不是整型的而是浮點型的,這樣一來,上面代碼中,將max,min置爲1就不妥了。

4. 將一個含有n個元素的數組向右循環移動k位,要求時間複雜度是O(n),且只能使用兩個額外的變量,這是在微軟的編程之美上看到的一道題。

#include <stdio.h>

void Reverse(int *s,int b, int e)
{
	for(; b < e; b++,e--)
	{
		s[b] = s[e] + s[b];
		s[e] = s[b] - s[e];
		s[b] = s[b] - s[e];
	}
}

void RightShift(int *s, int n,int k)
{
	Reverse(s,n-k,n-1);
	Reverse(s,0,n-k-1);
	Reverse(s,0,n-1);
}

int main()
{
	int i;
	int a[9] = {6,7,8,9,1,2,3,4,5};
	RightShift(a,9,5);
	for(i = 0 ; i < 9 ; i++)
		printf("%d ",a[i]);
	printf("\n");
	return 0;
}
相關文章
相關標籤/搜索