Day24 2023/03/24
难度:简单
题目1
有序(升序)顺序表中删除所有其值重复的元素,使表中元素不重复。
题目2
将两个有序(升序)顺序表合并成一个新的有序表
示例1
输入:1 2 2 3 3 3 4 4 5
输出:1 2 3 4 5
示例2
输入:
1 3 4
5 6 7
输出:1 3 4 5 6 7
题目1思路
由于是有序的顺序表,所以这里可以采用双指针法,具体步骤:
- 从前往后遍历顺序表,使用两个指针 i 和 j,其中 i 指向当前已处理好的无重复元素的最后一个位置, j 指向当前待处理的元素位置。
- 如果当前元素 L.data[j] 与前一个元素 L.data[i]不相等,则将其移到前面,即将其放在 i+1 的位置上,并将 i 指针向前移动一位。
- 最后修改顺序表的长度为 i+1,即为去重后的元素个数。
题目2思路
由于顺序表这种数据结构本身的限制,这里只能是用辅助顺序表的方式来实现!具体步骤:
- 定义一个新的有序顺序表C,用来存储合并后的有序表
- 使用三个指针 i、j 和 k 分别指向有序表A、B 和 C 的起始位置,其中 i 和 j 分别指向有序表A 和 B 的第一个元素,k 则指向新的有序表C 的第一个空闲位置。
- 依次比较有序表 A 和 B 中的元素,将较小的元素插入到有序表 C 中。具体操作是,如果 A.data[i] <= B.data[j],则将 A.data[i] 插入到 C.data[k] 中,否则将 B.data[j] 插入到 C.data[k] 中,然后将相应的指针向后移动一个位置。
- 循环执行步骤3,直到有序表A或B中的所有元素都被插入到有序表C中。
- 将剩余的有序表 A 或 B 中的元素插入到有序表 C 中。
- 设置新的有序顺序表C的长度为 k,即为合并后的有序表的长度
关键点
- 题目1中使用的方法,有些重复元素的删除,是通过更新表长实现的,是一种逻辑上的删除。
- 题目2中将剩余的有序表 A 或 B 中的元素插入到有序表 C 中,此时两个while循环只会执行其中一个,因为初次比较的时候已经将其中一个表中所有元素插入到表C中。
算法实现
c++代码实现-删除有序顺序表重复元素
#include <cstdio>
#include <iostream>
using namespace std;
#define MAXSIZE 100
// 定义有序顺序表的结构体
struct SeqList {
int data[MAXSIZE]; // 用数组存储数据
int length; // 顺序表长度
};
// 创建顺序表
bool CreateList(SeqList &L) {
int i = 0;
while (cin >> L.data[i++]) {
L.length++;
if (getchar() == '\n') {
break;
}
}
if (L.length > MAXSIZE) {
return false;
}
return true;
}
// 函数功能:从有序顺序表中删除所有重复元素,使表中元素不重复
void DeleteDuplicate(SeqList &L) {
int i, j;
for (i = 0, j = 1; j < L.length; j++) {
// 如果当前元素与前一个元素不相等,则将其移到前面
if (L.data[j] != L.data[i]) {
i++; // i指针指向下一个位置
L.data[i] = L.data[j]; // 将当前元素移到前面
}
}
L.length = i + 1; // 修改顺序表长度
}
int main() {
SeqList L; // 注意是有序顺序表!
CreateList(L);
DeleteDuplicate(L);
// 输出删除重复元素后的顺序表
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
return 0;
}
- 时间复杂度 --- 遍历整个顺序表,其中n为顺序表表长
- 空间复杂度 --- 无额外的辅助空间,仅常数级空间
c++代码实现-合并有序顺序表
#include <iostream>
using namespace std;
#define MAXSIZE 100
// 定义有序顺序表的结构体
struct SeqList {
int data[100]; // 用数组存储数据
int length; // 顺序表长度
};
// 创建顺序表
bool CreateList(SeqList &L) {
int i = 0;
while (cin >> L.data[i++]) {
L.length++;
if (getchar() == '\n') {
break;
}
}
if (L.length > MAXSIZE) {
return false;
}
return true;
}
// 函数功能:将两个有序顺序表合并成一个新的有序表
SeqList Merge(SeqList A, SeqList B) {
SeqList C; // 定义新的有序顺序表C
int i = 0, j = 0, k = 0; // i、j、k分别指向表A、B、C
while (i < A.length && j < B.length) {
// 将A和B中较小的元素放入C中
if (A.data[i] <= B.data[j]) {
C.data[k++] = A.data[i++];
} else {
C.data[k++] = B.data[j++];
}
}
// 将A和B中剩余的元素放入C中
while (i < A.length) {
C.data[k++] = A.data[i++];
}
while (j < B.length) {
C.data[k++] = B.data[j++];
}
C.length = k; // 设置新的有序顺序表C的长度
return C;
}
int main() {
SeqList A;
SeqList B;
CreateList(A); // 创建有序表A
CreateList(B); // 创建有序表B
SeqList C = Merge(A, B); // 合并A和B为新的有序顺序表C
// 输出合并后的有序顺序表C
for (int i = 0; i < C.length; i++) {
cout << C.data[i] << " ";
}
return 0;
}
- 时间复杂度 --- 遍历两个表,其中n、m分别为两个表表长
- 空间复杂度 --- 辅助表的长度为n+m,其中n、m分别为两个表表长
总结
- 本篇还是回忆顺序表,其中涉及到的操作,仍然在之前的题目中就接触过,但是要思考的是,对于不同的数据结构,去实现同一种或者类似的操作的时候,往往代码是需要针对性的去修改的,比如题目二中对于链表的话,就不需要辅助表,就可实现相同的操作!(😀)