😎蓝蓝计算机考研算法-day24顺序表回忆2删除、合并

265 阅读3分钟

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思路


由于是有序的顺序表,所以这里可以采用双指针法,具体步骤:

  1. 从前往后遍历顺序表,使用两个指针 i 和 j,其中 i 指向当前已处理好的无重复元素的最后一个位置, j 指向当前待处理的元素位置。
  2. 如果当前元素 L.data[j] 与前一个元素 L.data[i]不相等,则将其移到前面,即将其放在 i+1 的位置上,并将 i 指针向前移动一位。
  3. 最后修改顺序表的长度为 i+1,即为去重后的元素个数。

题目2思路


由于顺序表这种数据结构本身的限制,这里只能是用辅助顺序表的方式来实现!具体步骤:

  1. 定义一个新的有序顺序表C,用来存储合并后的有序表
  2. 使用三个指针 i、j 和 k 分别指向有序表A、B 和 C 的起始位置,其中 i 和 j 分别指向有序表A 和 B 的第一个元素,k 则指向新的有序表C 的第一个空闲位置。
  3. 依次比较有序表 A 和 B 中的元素,将较小的元素插入到有序表 C 中。具体操作是,如果 A.data[i] <= B.data[j],则将 A.data[i] 插入到 C.data[k] 中,否则将 B.data[j] 插入到 C.data[k] 中,然后将相应的指针向后移动一个位置。
  4. 循环执行步骤3,直到有序表A或B中的所有元素都被插入到有序表C中。
  5. 将剩余的有序表 A 或 B 中的元素插入到有序表 C 中。
  6. 设置新的有序顺序表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;
}
  • 时间复杂度 O(n)O(n)--- 遍历整个顺序表,其中n为顺序表表长
  • 空间复杂度 O(1)O(1)--- 无额外的辅助空间,仅常数级空间

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;
}
  • 时间复杂度 O(n+m)O(n+m)--- 遍历两个表,其中n、m分别为两个表表长
  • 空间复杂度 O(n+M)O(n+M)--- 辅助表的长度为n+m,其中n、m分别为两个表表长

总结

  • 本篇还是回忆顺序表,其中涉及到的操作,仍然在之前的题目中就接触过,但是要思考的是,对于不同的数据结构,去实现同一种或者类似的操作的时候,往往代码是需要针对性的去修改的,比如题目二中对于链表的话,就不需要辅助表,就可实现相同的操作!(😀)