1、从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错误信息并退出运行。
//删除顺序表L中的最小值元素结点,并通过引用类型参数e返回其值
bool Del_min(SqList &L, int &e)
{
if(L.length == 0)
return false;
int pos = 0
e = L.data[0];
for(i = 0 ; i < L.length; i++)
{
if(L.data[i] < e)
{
e = L.data[i];
pos = i;
}
}
L.data[pos] = L.data[L.length - 1];
L.length--;
return true;
}
2、设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
//将顺序表L的所有元素逆置,空间复杂度为O(1)
void Reverse(SqList &L)
{
int temp;
for(i = 0; i < L.length / 2 ; i++)
{
temp = L.data[i];
L.data[i] = L.data[L.length - 1 - i]
L.data[L.length - 1 - i] = temp;
}
}
3、对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,删除线性表中所有值为x的数据元素。
void del_x_1(SqList &L, int x)
{
int k = 0;
for(int i = 0; i < L.length; i++)
{
if(L.data[i] != x)
{
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
4、从有序顺序表中删除其值在[s,t]之间的所有元素,若s或t不合理或顺序表为空,则显示出错误信息并退出运行。
解法一(有点暴力):
//有序顺序表中删除其值在[s,t]之间的所有元素
bool Del_s_t2(SqList &L, int s, int t)
{
int k = 0;
if(s >= t || L.length == 0)
return false;
for(int i = 0; i < L.length; i++)
{
if((L.data[i] < s) || (L.data[i] > t))
{
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
解法二(基于有序的最优解):
bool Del_s_t2(SqList &L, int s, int t)
{
int i, j;
if(s >= t || L.length == 0)
return false;
for(i = 0; i < L.length && L.data[i] < s; i++); //寻找大于等于s的第一个元素
if(i >= L.length)
return false;
for(j = i; j < L.length && L.data[j] <= t; j++); //寻找第一个大于t的元素
for(;j < L.length; i++, j++)
L.data[i] = L.data[j];
L.length = i;
return true;
}
5、从顺序表中删除其值在给定值s与t之间(要求 s < t)的所有元素,若s或t不合理或顺序表为空,则显示出错误信息并退出运行。
也许暴力解就是最优解,和上一题的第一种解法相同:
bool Del_s_t2(SqList &L, int s, int t)
{
int k = 0;
if(s >= t || L.length == 0)
return false;
for(int i = 0; i < L.length; i++)
{
if((L.data[i] < s) || (L.data[i] > t))
{
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
6、从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。
//有序表中删除所有值相同的元素(保留一个)
void Delete_Same(SqList &L)
{
int i, j;
for(i = 0, j = 1; j < L.length; j++)
{
if(L.data[i] != L.data[j])
L.data[++i] = L.data[j];
}
L.length = i + 1;
}
7、将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
//将两个有序顺序表合并为一个有序顺序表
bool Merge(SqList A, SqList B, SqList &C)
{
if(A.length + B.length > C.MaxSize)
return false;
int i = 0, j = 0, k = 0;
while(i < A.length && j < B.length)
{
if(A.data[i] < B.data[j])
C.data[k++] = A.data[i++];
else
C.data[k++] = B.data[j++]
}
while(i < A.length)
C.data[k++] = A.data[i++];
while(j < B.length)
C.data[k++] = B.data[j++];
C.length = k;
return true;
}
8、已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3~am)和(b1,b2,b3~bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3~bn)放在(a1,a2,a3~an)前面。
垃圾的暴力解:将A[0]与A[m]互换,再将A[1]与A[m+1]互换,一直到将A[m-1]与A[m+n-1]互换,如果此时A[m+n-1]之后还有元素,说明n>m,则把这些元素全部放到A[m]及之后的位置,将已调整的元素往后移。
最优解:将A[m+n]中的元素全部逆置,再将前n个元素与后m个元素分别使用逆置算法。
void Reverse(int A[], int left, int right, int MaxSize)
{
if(right <= left || right >= MaxSize)
return false;
int mid = (right + left) / 2;
for(int i = 0; i < mid; i++)
{
int temp = A[left + i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
void Exchange(int A[], int m, int n, int MaxSize)
{
Reverse(A, 0, n + m - 1, MaxSize);
Reverse(A, 0, n - 1, MaxSize);
Reverse(A, n, m + n - 1,MaxSize);
}
9、线性表(a1,a2,a3~an)中的元素递增有序且按顺序存储与计算机内,要求设计一个算法,完成用最少时间在表中查找数值为x的元素,并将其与后继元素位置交换。若找不到,则将其插入表中并使表中元素仍递增有序。
void SearchExchangeInsert(SqList &L, int x)
{
int low = 0, high = n - 1, mid,temp = 0;
while(low <= high)
{
mid = (low + high) / 2;
if(L.data[mid] == x)
break;
if(L.data[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
if(L.data[mid] == x && mid != n - 1)
{
temp = L.data[mid];
L.data[mid] = L.data[mid + 1];
L.data[mid + 1] = temp;
}
if(low > high)
{
for(i = n-1 ; i > high; i--)
A[i + 1] = A[i];
A[i + 1] = x;
}
}
10、设将n(n>1)个整数存到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1,~,Xn-1)变换为(Xp,Xp+1,~,Xn-1,X0,X1,~,Xp-1)。要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
(3)说明你所设计算法的时间复杂度和空间复杂度。
解法一(暴力解)
/*基本设计思想:用t保存数组首元素,将其余元素向左移动一个单位,
再将数组首元素加到末尾,即完成了循环左移一位。这样进行p次即完
成了循环左移p位。*/
//时间复杂度为O(pn)即O(n),空间复杂度为O(1)。
#include <iostream>
using namespace std;
int main()
{
int R[5] = {1, 2, 3, 4, 5};
int len = 5, p = 0;
scanf("%d", &p);
for(int i = 0; i < p; i++)
{
int t = R[0];
for(int j = 1; j < 5; j++)
R[j - 1] = R[j];
R[4] = t;
}
for(int i = 0; i < 5; i++)
printf("%d", R[i]);
}
解法二(最优解):
/*可以将问题是为把数组ab转换为ba(a为前n个元素,b后n-p个元素),
先将a逆置,再将b逆置,然后对新数组再整体逆置即可。*/
/*三个Reverse时间复杂度为O(p/2),O((n-p)/2),O(n/2),故为O(1),
空间复杂度为O(1)。*/
void Reverse(int R[], int from, int to)
{
int temp;
for(int i = from; i < (from + to)/2; i++)
{
temp = R[i];
R[i] = R[to -i];
R[to - i] = temp;
}
}
void Converse(int R[], int n, int p)
{
Reverse(R, 0, p - 1);
Reverse(R, p, n - 1);
Reverse(R, 0, n - 1);
for(int i = 0; i < 5; i++)
{
printf("%d", R[i]);
}
}
11、题目略
编了一下午的次优解:
/*A和B两个序列,用i遍历A,用j遍历B,当A[i]<B[j]时,
假装将其装入一个升序序列中,用pos表示其中的元素,
是谁最后时pos变成(L/2)向上取整,就将谁打印出来。*/
/*时间复杂度为O(n),空间复杂度为O(1)*/
#include <iostream>
using namespace std;
int Merge(int A[], int B[])
{
int pos = 0, j = 0, i = 0;
while(j < 5 && i < 5)
{
if(A[i] > B[j])
{
j++;
pos++; //记录元素的位序
if(pos == (10 + 2 - 1)/2)
{
printf("%d\n", pos);
return B[j - 1];
}
}
else
{
i++;
pos++;
if(pos == (10 + 2 - 1)/2)
{
printf("%d\n", pos);
return A[i - 1];
}
}
}
while(i < 5)
{
pos++;
if(pos == (10 + 2 - 1)/2)
{
printf("%d\n", pos);
return A[i - 1];
}
i++;
}
while(j < 5)
{
pos++;
if(pos == (10 + 2 - 1)/2)
{
printf("%d\n", pos);
return B[j - 1];
}
j++;
}
}
int main()
{
int z;
int S1[5] = {1, 3, 5, 7, 9};
int S2[5] = {11, 13, 15, 17, 19};
z = Merge(S1,S2);
printf("%d",z);
}
暴力解:
/*暴力解就是额外设置一个数组C用来存放已排好序的队列,
再求其中位数,因为两个等长序列,故数组C长度为偶数,
中位数为L/2*/
/*时间复杂度为O(n),空间复杂度为O(n)*/
#include <iostream>
using namespace std;
int Merge(int A[], int B[])
{
int i = 0, j = 0, k = 0, C[12];
while(i < 6 && j < 6)
{
if(A[i] <= B[j])
C[k++] = A[i++];
else
C[k++] = B[j++];
}
while(i < 6)
C[k++] = A[i++];
while(j < 6)
C[k++] = B[j++];
return C[k / 2];
}
int main()
{
int z;
int S1[6] = {1, 3, 5, 7, 9,10};
int S2[6] = {11, 13, 15, 17, 19, 20};
z = Merge(S1,S2);
printf("%d",z);
return 0;
}
12、题目略
暴力解:
/*暴力解,设置哈希表来存储数组A中各元素出现的次数,
再用for循环来比较哈希表中各元素出现的次数,
最后if判断出现次数最多的次数是否大于n/2*/
/*时间复杂度为O(n),空间复杂度为O(n)*/
#include <iostream>
using namespace std;
int nums[100] = {0};
int Findzhu(int A[])
{
int i,maxx = 0, c = 0;
for(i = 0; i < 6; i++)
{
nums[A[i]]++;
}
for(i = 0; i < 6; i++)
{
if(A[i] > maxx)
maxx = A[i];
}
for(i = 0; i <= maxx; i++)
{
if(c < nums[i])
c = i;
}
if(nums[c] > 6/2)
return c;
return -1;
}
int main()
{
int z;
int A[6] = {1, 9, 9, 9, 9,5};
z = Findzhu(A);
printf("%d",z);
return 0;
}
13、题目略
暴力解:
/*暴力解*/
/*时间复杂度为O(n^2),空间复杂度为O(n)*/
#include <iostream>
using namespace std;
int FindMissMin(int A[])
{
int i = 0, j, k = 1;
while(i < 4)
{
if(A[i] < 0)
i++;
if(A[i] != k)
i++;
else
{
i = 0;
k++;
}
}
return k;
}
int main()
{
int z;
int A[4] = {5, -3, 1, 3};
z = FindMissMin(A);
printf("%d",z);
return 0;
}
少暴力一点的解法,先用1和数组元素依次对比,若没有等于1的元素,则返回1,若数组中有1,则把num置0后再用2和数组元素对比..........
int FindMissMin(int A[])
{
int i, num = 0;
for(i = 1; ; i++)
{
for(int j = 0; j < n; j++)
{
if(i == A[j])
num++;
}
if(num == 0)
return i; //i就是要找的最小正整数
else
num = 0;
}
}
14、题目略
暴力解(非常暴力):
/*暴力解*/
/*时间复杂度为O(n^3),空间复杂度为O(n)*/
#include <iostream>
using namespace std;
void FindminoTrip(int A[], int B[], int C[])
{
int i, j, k, d;
int min_d = abs(A[0] - B[0]) + abs(B[0] - C[0]) + abs(C[0] - A[0]);
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
for(k = 0; k < 5; k++)
{
d = abs(A[i] - B[j]) + abs(B[j] - C[k]) + abs(C[k] - A[i]);
if(d < min_d)
min_d = d;
}
}
}
printf("最小距离为%d\n", min_d);
printf("三元组为:",A[i], B[j], C[k]);
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
for(k = 0; k < 5; k++)
{
if(min_d == abs(A[i] - B[j]) + abs(B[j] - C[k]) + abs(C[k] - A[i]))
printf("(%d,%d,%d)\n",A[i], B[j], C[k]);
}
}
}
}
int main()
{
int S1[3] = {-1, 0, 9};
int S2[4] = {-25, -10, 10, 11};
int S3[5] = {2, 9, 17, 30, 41};
FindminoTrip(S1, S2, S3);
return 0;
}