线性表
10.2010统考真题
1)
答:循环左移即相当于将前面的p个元素和后面的(n -p) 个元素换一次位置,所以我可以先对整个数组进行一次逆转,再对前面的( (n-p)个元素进行逆转,和后面的p个元素进行逆转。
2)
void Reverse(int* R,int low,int high){ while(low < high){ int temp = R[low]; R[low] = R[high]; R[high] = temp; low++; high--; } return; } void Shift(int *R,int p,int n){ Reverse(R,0,n-1); Reverse(R,0,n-p-1); Reverse(R,n-p,n-1); return; } //用于测试的main函数 int main(){ int *r; r = new int[10]; for(int i = 0;i < 10;i++){ r[i] = i; } for(int i = 0;i < 10;i++){ cout << r[i] << " "; } Shift(r,4,10); cout<<endl; for(int i = 0;i < 10;i++){ cout << r[i] << " "; } return 0; }
3)
答:时间复杂度是O(n),空间复杂度是O(1)。
11.2011统考真题
1)
答:因为给出的两个数组已经是按照升序进行排列,所以我们不需要再进行排序,直接进行比较。而且两个数组是等长的,所以 L/2 一定是一个整数,所以我们提前计算好中位数所在数组中的序号,然后将两个数组的元素从头到尾比较大小,计数至L/2就是我们所要求的结果。
2)
int FindMidNum(int *A,int *B,int n){ int i = 0,j = 0; int target = n; int count = 0; int ans = 0; while(i < n && j < n){ if(A[i] <= B[j]){ ans = A[i]; i++; count++; } else{ ans = B[j]; j++; count++; } if(count == target){ return ans; } } while(i < n){ ans = A[i]; count++; i++; if(count == target){ return ans; } } while(j < n){ ans = B[j]; count++; j++; if(count == target){ return ans; } } return ans; } //用于测试的main函数 int main() { int* a, * b; a = new int[10]; b = new int[10]; for (int i = 0; i < 10; i++) { a[i] = i + 1; b[i] = i + 3; } for (int i = 0; i < 10; i++) { cout << a[i] << " "; } cout << endl; for (int i = 0; i < 10; i++) { cout << b[i] << " "; } cout << endl; cout << FindMidNum(a, b, 10); return 0; }
3)
答:时间复杂度O(n),空间复杂度O(1)
12.2013统考真题
1)
答:我们可以采用哈希的思想,因为每一个元素的值是大于等于0小于n的,所以我们可以开辟一个长度为n的辅助数组,b[i]的值表示整数序列A中元素值为i的个数,然后找出数组b[i]中的最大值,若最大值大于n/2,则下标i就是序列A中的主元素,否则返回-1表示没有主元素。2)
int FindMostNum(int *a,int n){ int *b = new int[n]; memset(b,0,sizeof(int) * 10); for(int i = 0;i < n;i++){ b[a[i]]++; } int max = -1; int index = 0; for(int i = 0;i < n;i++){ if(b[i] > max){ max = b[i]; index = i; } } if(max > n /2){ return index; } else{ return -1; } }
3)
答:时间复杂度O(n),空间复杂度O(n)
13.2018统考真题
1)
答:数组中一共有n个元素,我们可以设置一个长度为n的辅助数组,我们用a[i]来标识为i+1的正整数有没有在该数组中出现,则会出现两种情况:
- a[i]的值均为1,那么意味着1-n均在原数组中出现,即未出现的最小正整数为n+1
- a[i]中有的值为0,下标+1的值就没有在原数组中出现,那么从左到右遍历a数组,第一个值为0的下标+1就是未出现的最小正整数
2)
int FindDisapper(int *r,int n){ bool *b = new bool[n]();//cpp默认赋值为false for(int i = 0;i < n;i++){ if(r[i] <= n){ b[r[i] - 1] = true; } } for(int i = 0;i < n;i++){ if(b[i] == false){ return i+1; } } return n+1; }
3)
答:时间复杂度O(n),空间复杂度O(n);
14.2020统考真题
1)
答:
a=b=c,那么距离D=0;
无妨设a<b<c,那么由|a-b|表示a到b的距离,|b-c|表示b到c的距离就可以得知|a-b|+|b-c|表示a到c的距离,那么D就是二倍的|a-c|,即二倍的a到c的距离。
所以我们可以设三元组中最小的数为a,最大的数为c,那么D就是2(c-a),又因为三个数组中的元素都是按照升序排列的,所以我们可以从头开始遍历,计算出一个三元组的D之后与之前的进行比较,如果比之前的小则替换之,然后我们找到三元组中最小的那个元素是来自于哪一个数组,然后让他的下标+1,此时a变大,则D减小,当某一个数组遍历结束的时候,此时结束循环,因为如果三元组中的另外两个元素继续增大,会使D的值增大。如果循环期间得到D的值为0,则可以直接退出循环。
2)
//计算绝对值 int MyAbs(int a,int b){ return a>b?a-b:b-a; } //判断是否是最小的数 bool IsMinNum(int a,int b,int c){ if(a<=b && a<=c) return true; else return false; } int MinDistance(int *s1,int *s2,int *s3,int n1,int n2,int n3){ int i = 0,j = 0,k = 0; int minDistance = 0x7fffffff; while(i<n1 && j<n2 && k<n3 && minDistance>0){ int temp = MyAbs(s1[i],s2[j])+MyAbs(s2[j],s3[k])+MyAbs(s1[i],s3[k]); if(temp < minDistance) minDistance = temp; if(IsMinNum(s1[i],s2[j],s3[k])) i++; else if(IsMinNum(s2[j],s1[i],s3[k])) j++; else k++; } return minDistance; }
3)
答:时间复杂度O(n),空间复杂度O(1).