【王道数据结构-第二章-线性表算法题】

第二章-线性表算法题 笔记记录

1.从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。

#include <iostream>
#define MAXSIZE 5
typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;

/**
* 从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
* 解析:记录最小值和最小值位置然后进行置换就行
 */
bool deleteMinElement(SeqList &seqList, int &value) {
    if (seqList.length == 0) {
        return false;
    }
    int pos = 0;
    int minValue = seqList.data[0];
    for (int i = 1; i < seqList.length; i++) {
        if (seqList.data[i] < minValue) {
            minValue = seqList.data[i];
            pos = i;
        }
    }
    seqList.data[pos] = seqList.data[seqList.length - 1];
    value=minValue;
    seqList.length--;
    return true;
}

int main() {
    SeqList seqList;
    seqList.length = 5;
    srand((unsigned) time(NULL));
    for (int i = 0; i < seqList.length; i++) {
        seqList.data[i] = rand() % 100;
        printf("%d ", seqList.data[i]);

    }
    int value=0;
    //输出最小值
    if (deleteMinElement(seqList, value)) {
        printf("\n");
        for (int i = 0; i < seqList.length; i++) {
            printf("%d ", seqList.data[i]);
        }
        printf("\n");
        printf("最小值:%d", value);
    } else {
        printf("没有最小值\n");
    }
    return 0;
}


2. 设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。

#include <iostream>
#define MAXSIZE 5
typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
/**
 * 计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
 * 解析:就是对调元素位置
 */
void invert(SeqList &seqList) {
        for (int i = 0; i < seqList.length / 2; i++) {
        int temp = seqList.data[i];
        seqList.data[i] = seqList.data[seqList.length - 1 - i];
        seqList.data[seqList.length - 1 - i] = temp;
    }
}

int main() {
    SeqList seqList;
    seqList.length = 5;
    srand((unsigned) time(NULL));
    for (int i = 0; i < seqList.length; i++) {
        seqList.data[i] = rand() % 100;
        printf("%d ", seqList.data[i]);

    }
    invert(seqList);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}


3. 对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为 O(1)的算法,该算法删除顺序表中所有值为x的数据元素。

#include <iostream>
#define MAXSIZE 5
typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
/**
* 对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为 O(1)的算法,该算法删除顺序表中所有值为x的数据元素。
* 解析:相当于再来一个标记位,从头开始重新赋值不是x的元素到列表中
 */
void deleteX(SeqList &seqList, int x) {
    int k = 0;
    for (int i = 0; i < seqList.length; i++) {
        if (seqList.data[i] != x) {
            seqList.data[k++] = seqList.data[i];
        }
    }
    seqList.length = k;
}

/**
 * 
 * @param seqList 
 * @param x
 * 解析: 每次移动都记录k的个数,到下一个不是k元素时向前移动k个元素
 */
void deleteX2(SeqList &seqList, int x) {
    int k = 0, i = 0;;
    while (i < seqList.length) {
        if (seqList.data[i] == x) {
            k++;
        } else {
            //当前元素不是x,将当前元素移动k个元素的距离
            seqList.data[i - k] = seqList.data[i];
        }
        i++;
    }
    seqList.length -= k;
}
int main() {
    SeqList seqList;
    seqList.length = 5;
    srand((unsigned) time(NULL));
    for (int i = 0; i < seqList.length; i++) {
        seqList.data[i] = rand() % 10;
        printf("%d ", seqList.data[i]);

    }
    deleteX(seqList, 5);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}


4. 从顺序表中删除其值在给定值s和t之间(包含s和t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行。

#include <iostream>
#define MAXSIZE 5

typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
/**
* 从顺序表中删除其值在给定值s和t之间(包含s和t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行。
* 解析:与第3题类似,用k做标记为从头开始扫,仅把不需要删除的赋值到列表中
 */
bool deleteRange(SeqList &seqList, int s, int t) {
    if (s >= t || seqList.length == 0) {
        return false;
    }
    int k = 0;
    for (int i = 0; i < seqList.length; i++) {
        if (seqList.data[i] < s || seqList.data[i] > t) {
            seqList.data[k++] = seqList.data[i];
        }
    }
    seqList.length = k;
    return true;
}

/**
 *
 * @param seqList
 * @param s
 * @param t
 * 解析:记录删除的个数,从第一个开始扫,遇到需要删除的元素,记录个数,否则赋值到列表中
 */
bool deleteRange2(SeqList &seqList, int s, int t) {
    int k = 0, i = 0;
    if (s >= t || seqList.length == 0) {
        return false;
    }
    for (int i = 0; i < seqList.length; i++) {
        if (seqList.data[i] >= s && seqList.data[i] <= t) {
            k++;
        } else {
            seqList.data[i - k] = seqList.data[i];
        }
    }
    seqList.length -= k;
    return true;
}

int main() {
    SeqList seqList;
    seqList.length = 5;
    srand((unsigned) time(NULL));
    for (int i = 0; i < seqList.length; i++) {
        seqList.data[i] = rand() % 10;
        printf("%d ", seqList.data[i]);
    }
    deleteRange(seqList, 2, 5);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

5. 从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。

#include <iostream>
#define MAXSIZE 50

typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;

/**
 * 5.从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。
 * 解析:题目说有序的,所以用两个指针,一个指向当前元素,一个指向下一个元素,如果当前元素和下一个元素相等,则删除下一个元素,否则当前元素向后移动
 * 与第3题类似,用k做标记为从头开始扫,仅把不需要删除的赋值到列表中
 * 其次注意这里要先++,也就是++k因为我们默认第一个元素就是不重复列表的第一个所以遇到下一个要从第二个开始放置,所以是++k
 */
bool deleteRepeat(SeqList &seqList) {
    if (seqList.length == 0) {
        return false;
    }
    int k=0;
    for (int i=1; i < seqList.length; i++) {
        if (seqList.data[k] != seqList.data[i]) {
            seqList.data[++k] = seqList.data[i];
        }
    }
    seqList.length = k + 1;
    return true;
}

int main() {
    SeqList seqList={1, 1, 1, 2, 2, 3, 3, 3, 4, 4};
    seqList.length = 10;
    deleteRepeat(seqList);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

6. 两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。

#include <iostream>
#define MAXSIZE 50

typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;

/**
 * 6.两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
 * 解析:第3题的升级版本 k还是新队列的标识位,然后比较两个list的大小 谁小的就先放置,然后i++或者j++ k++直到有一个放完剩下
 * 的两个while实际就是把另一个列表的元素放完
 */

bool mergeSeqList(SeqList &seqList1, SeqList &seqList2, SeqList &seqList3) {
    if (seqList1.length + seqList2.length > seqList3.length) {
        return false;
    }
    seqList3.length = seqList1.length + seqList2.length;
    int i = 0, j = 0, k = 0;
    while (i < seqList1.length && j < seqList2.length) {
        if (seqList1.data[i] < seqList2.data[j]) {
            seqList3.data[k++] = seqList1.data[i++];
        } else {
            seqList3.data[k++] = seqList2.data[j++];
        }
    }
    while (i < seqList1.length) {
        seqList3.data[k++] = seqList1.data[i++];
    }
    while (j < seqList2.length) {
        seqList3.data[k++] = seqList2.data[j++];
    }
    seqList3.length=k;
    return true;
}

int main() {
    SeqList seqList = {1, 1, 2, 3, 3, 4, 5, 6, 7, 8};
    SeqList seqList2 = {1, 2,3,5};
    seqList.length = 10;
    seqList2.length = 4;
    SeqList seqList3;
    mergeSeqList(seqList, seqList2, seqList3);
    printf("\n");
    for (int i = 0; i < seqList3.length; i++) {
        printf("%d ", seqList3.data[i]);
    }
    return 0;
}

7. 知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,⋯,am)和(b1,b2,b3,⋯,bn,)。编写个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,⋯,bn,)放在(a1,a2,a3,⋯,am)的前面。

/**
* 7.知在一维数组A[m+n]中依次存放两个线性表(a?,a?,a?,⋯,am)和(b?,bz,b?,⋯,b,)。编写个函数,将数组中两个顺序表的位置互换,即将(b?,bz,b?,⋯,b,)放在(aj,a?,a?,⋯,am)的前面。
* 解析:假设两个list分别是m和n 要互换位置 最简单的办法是直接换,但是直接换完与原来逆序,所以再局部换两次。
 * @return
 */
#include <iostream>
#define MAXSIZE 50

typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
 
bool invert2(SeqList &seqList, int left, int right) {
    if (left > right) {
        return false;
    }
    while (left < right) {
        int temp = seqList.data[left];
        seqList.data[left] = seqList.data[right];
        seqList.data[right] = temp;
        left++;
        right--;
    }
    return true;
}
bool swap(SeqList &seqList, int m, int n) {
    if (m + n > seqList.length) {
        return false;
    }
    invert2(seqList, 0, m + n-1);
    invert2(seqList, 0, n-1);
    invert2(seqList, n, m + n-1);
    seqList.length = m + n;
    return true;
}
int main() {
    SeqList seqList = {1, 2, 3, 4, 5, 6,7};
    seqList.length = 7;
    swap(seqList, 3, 4);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

8. 线性表(a1,a2,a3,⋯,an,)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法,完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换

/**
* 8.线性表(a1,a2,a3,⋯,an,)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法,完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换,
* 若找不到,则将其插入表中并使表中元素仍递增有序。
* 解析:有序列表时间最少 二分查找 这里利用二分查找会有两种情况
* 第一种是找到了 则目标值与目标值的后继互换(注意:如果目标值是最后一个元素无需互换)
* 第二种没找到 则插入目标值并且目标值之后的后移,这里如果没找到利用low<=high的判断条件的话没找到的时候high【必定在要插入位置的前一个位置】
* @return
*/
#include <iostream>
#define MAXSIZE 50
typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
bool searchAndSwap(SeqList &seqList, int x) {
    int low = 0, high = seqList.length - 1, mid;
    while (low <= high) {
        mid = (low + high) / 2;
        if (seqList.data[mid] == x) {
            break;
        } else if (seqList.data[mid] < x) {
            low = mid + 1;
        } else {
            high = mid - 1;
        }
    }
    //找到了x并且不是最后一位要参与交换
    if (seqList.data[mid] == x && mid != seqList.length - 1) {
        int temp = seqList.data[mid];
        seqList.data[mid] = seqList.data[mid + 1];
        seqList.data[mid + 1] = temp;
    }
    //没找到 插入之后的后移
    if (low > high) {
        seqList.length++;
        int i;
        for ( i = seqList.length - 1; i > high; i--) {
            seqList.data[i + 1] = seqList.data[i];
        }
        seqList.data[high + 1] = x;
    }
    return true;
}
int main() {
    SeqList seqList = {1, 3, 3, 4, 4, 6, 7};
    seqList.length = 7;
    searchAndSwap(seqList, 5);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

9. 给定三个序列 A、B、C,长度均为 n,且均为无重复元素的递增序列,请设计一个时间上尽可能高效的算法,逐行输出同时存在于这三个序列中的所有元素。例如,数组A为{1,2,3],数组B为{2,3,4],数组C为{-1,0,2},则输出2。

#include <iostream>
#define MAXSIZE 50
typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
/**
*9.给定三个序列 A、B、C,长度均为 n,且均为无重复元素的递增序列,请设计一个时间上尽可能高效的算法,逐行输出同时存在于这三个序列中的所有元素。例如,数组A为
{1,2,3],数组B为{2,3,4],数组C为{-1,0,2},则输出2。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或 C+语言描述算法,关键之处给出注释。
3)说明你的算法的时间复杂度和空间复杂度。
 * @return
 * 解析:这里看题解用了max函数,第一次没想明白为啥要找最大的,其实对三个列表的元素稍微列举下就知道,如果每个列表第一个元素都不一样,那么能出现重复元素的只能是
 * 三个列表中最大的那个元素重复,因为是递增数列,只能是列表第一个位置的最大值重复所以我们就以最大值作为思路,先求出最大值 看看其他队列是否有与最大值相同的,如果前进一位后没有
 * 最大值,且最大值变化了,则原来的最大值必没有相同项,以此类推
 * 找到为止
 *
 * 时间复杂度为O(n) 空间复杂度为O(1)
 */
int getMaxValue(int a, int b) {
    return a > b ? a : b;
}
bool printCommonElement(SeqList &seqList1, SeqList &seqList2, SeqList &seqList3) {
    int i = 0, j = 0, k = 0;
    while (i < seqList1.length && j < seqList2.length && k < seqList3.length) {
        if (seqList1.data[i] == seqList2.data[j] && seqList2.data[j] == seqList3.data[k]) {
            printf("%d ", seqList1.data[i]);
            i++;
            j++;
            k++;
        } else {
            int max=getMaxValue(seqList1.data[i],getMaxValue(seqList2.data[j],seqList3.data[k]));
            if (seqList1.data[i]<max) i++;
            if (seqList2.data[j]<max) j++;
            if (seqList3.data[k]<max) k++;

        }
    }
}

int main() {
    SeqList seqList = {1, 3, 4};
    SeqList seqList2 = {1, 2, 3};
    SeqList seqList3 = {-1, 2, 3};
    seqList.length = 3;
    seqList2.length = 3;
    seqList3.length = 3;
    printCommonElement(seqList, seqList2, seqList3);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

10. 设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0、X1,⋯,Xn-1)变换为(Xp,Xp+1,⋯,Xn-1,X0,X1,⋯,Xp-1)

#include <iostream>
#define MAXSIZE 50

typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
bool invert2(SeqList &seqList, int left, int right) {
    if (left > right) {
        return false;
    }
    while (left < right) {
        int temp = seqList.data[left];
        seqList.data[left] = seqList.data[right];
        seqList.data[right] = temp;
        left++;
        right--;
    }
    return true;
}/**
*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)说明你所设计算法的时间复杂度和空间复杂度。
*解析:对于数列123456
*左移2 得到:3456 12
*左移3 得到:456 123
*左移4 得到:56 1234
*左移5 得到:6 12345
*不难看出规律:先将前半部分反转,再反转后半部分,再反转整个数列即结果
 */
bool leftMove(SeqList &seqList, int p) {
    if (p <= 0 || p >= seqList.length) {
        return false;
    }
    invert2(seqList, 0, p-1);
    invert2(seqList, p, seqList.length-1);
    invert2(seqList, 0, seqList.length-1);
    return true;
}
int main() {
    SeqList seqList = {0, 1, 2,3,4};
    seqList.length = 5;
    leftMove(seqList,4);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

11. 一个长度为 L(L≥1)的升序序列S,处在第【L/2】个位置的数称为S的中位数。例如,若序列S1=(11,13,15,17,19),则S?的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1和S2的中位数是11。现在有两个等长升序序列 A和 B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。

#include <iostream>
#define MAXSIZE 50

typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;
bool getMedian(SeqList &seqList1, SeqList &seqList2) {
    int sumLength = seqList1.length + seqList2.length;
    int mid = sumLength / 2;
    int k = 0;
    int i = 0, j = 0;
    while (k < mid) {
        if (seqList1.data[i] < seqList2.data[j]) {
            i++;
            k++;
            if (k == mid) {
                printf("%d", seqList1.data[i - 1]);
            }
        } else {
            j++;
            k++;
            if (k == mid) {
                printf("%d", seqList2.data[j - 1]);
            }
        }
    }
    return true;
}
int main() {
    SeqList seqList = {1, 2, 5, 7, 9, 11};
    SeqList seqList2 = {1, 2, 4, 6, 8, 9};
    seqList.length = 6;
    seqList2.length = 6;
    getMedian(seqList2, seqList);
    printf("\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d ", seqList.data[i]);
    }
    return 0;
}

12. 简而言之就是如果一个数组中出现的相同元素个数大于 list.length/2 则说明这个数是主元素,原题放图

在这里插入图片描述

/**
 * 12.简而言之就是如果一个数组中出现的相同元素个数 大于 list.length/2 则说明这个数是主元素
 * @return
 * 1,2,5,9,5,9,5,5,5
 * 解析:摩尔投票 不多说
 */
int getMajorityElement(SeqList &seqList) {
    int count = 0;
    int value = seqList.data[0];
    for (int i = 0; i < seqList.length; i++) {
        if (seqList.data[i] == value) {
            count++;
        } else {
            count--;
        }
        if (count == 0) {
            value = seqList.data[i];
            count = 1;
        }
    }
    count = 0;
    for (int i = 0; i < seqList.length; i++) {
        if (seqList.data[i] == value) {
            count++;
        }
    }
    if (count > seqList.length / 2) {
        printf("主元素是:%d", value);
        return value;
    } else {
        return -1;
    }
}

13. 找出数组中的最小正整数

在这里插入图片描述

/**
 * 13.找出数组中的最小正整数    {-5,3,2,3}=1  {1,2,3}=4
 * 解析:建立一个桶来放值,每个桶都去放1-n的正整数值,n个数的列表最小值肯定是1-n的某一位最后遍历桶,如果桶中有0,则说明最小正整数是这个
 * @return
 */
int getMinPositiveInteger(SeqList &seqList) {
    int n = seqList.length;
    SeqList B;
    B.length = n;
    for (int i = 0; i < n; i++) {
        B.data[i] = 0;
    }
    int i;
    for (i = 0; i < seqList.length; i++) {
        if (seqList.data[i] > 0 && seqList.data[i] <= n) {
            B.data[seqList.data[i] - 1] = 1;
        }
    }
    for (int i = 0; i < n; i++) {
        if (B.data[i] == 0) {
            printf("最小正整数是:%d", i + 1);
            return i + 1;
        }
    }
}

14. 三元组

在这里插入图片描述

/**
 * 14.三元组
 * @return
 * 暴力一下
 */
int abs(int a) { return a < 0 ? -a : a; }

int GetMinDistance(int a[], int aa, int b[], int bb, int c[], int cc) {
    int min = 10000000;
    for (int i = 0; i < aa; i++) {
        for (int j = 0; j < bb; j++) {
            for (int k = 0; k < cc; k++) {
                int d = 0; //d用于记录距离
                d = abs(a[i] - b[j]) + abs(b[j] - c[k]) + abs(c[k] - a[i]);
                if (min > d) {
                    //如果出现更小的距离,进行替换
                    min = d;
                }
            }
        }
    }
    return min;
}
int main() {
    int a[3]={-1,0,9};
    int b[4]={-25,-10,10,11};
    int c[5]={2,9,17,30,41};
    printf("最小距离为:%d\n",GetMinDistance(a,3,b,4,c,5));
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱喝阔落的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值