409王道数据结构强化——算法题(二)

简介: 409王道数据结构强化——算法题

6.真题(只考虑次优解和暴力解)

6.1.数组

6.1.1.(2010)2cd73f5c19f640678b401bb0f12399e1.png

(1)新建一个与arr数组等长的数组arr,先将arr的后p个元素依次存放到res数组的前p个元素中,然后再将arr的剩余元素依次存放到res的剩余元素中

int* Reverse(int arr[], int n, int p) {
    int *res = (int*)malloc(sizeof(n));
    memset(a, 0, sizeof(int) * n);
    int i, j;
    for (i = n - p + 1, j = 0; i < n; i++, j++) res[j] = arr[i];
    for (i = 0; i < n - p + 1; i++, j++) res[j] = arr[i];
}

(3)O(n),O(n)

6.1.2.(2011)7b55667b406142e59b5943b9b605081b.png

(1)都放入新数组中快速排序

int Partation(int arr[], int low, int high) {
    随机将数组中某一元素和arr[low]交换    //快排优化
    int pivot = arr[low];    //选择arr[low]为基准元素
    while (low < high) {    
        while (low < high && arr[high] >= pivot) high--;    
        arr[low] = arr[high];
        while (low < high && arr[low] < pivot) low++;
        arr[high] = arr[low];
    }
    arr[low] = pivot;
    return low;
}
void QuickSort(int arr[], int low, int high) {
    if (low < high) {
        int pivotPos = Partation(arr, low, high);
        QuickSort(arr, low, pivotPos - 1);
        QuickSort(arr, pivotPos + 1, high);
    }
}
int GetMidNum(int A[], int B[], int len){
    int* C = (int*)malloc((sizeof(int) * (2 * len))    //新建长度为2len的数组C
    int i,j;
    for (i = 0; i < len; i++) C[i] = A[i];    //将数组A复制到数组C的前半段中
    for (j = 0; j < len; i++, j++) C[i] = B[j];    //将数组B复制到数组C的后半段中
    QuickSort(C, 0, 2 * len - 1);    //对数组C进行快速排序
    cout << C[len - 1];    //输出中位数
}

(2)数组指针后移把数存入第三个数组(用count记录进行次数的方法并不能降低时间复杂度,省略系数后还是n的时间复杂度)

int GetMidNum(int A[], int B[], int len) {
    int *C = (int*)malloc(sizeof(int) * 2 * len);
    int i, j, k;
    for(i = 0, j = 0, k = 0; i < len && j < len; k++){    
        if (A[i] < B[j]) {    //比较A[i]和B[j],更小的存入C,并且该数组的指针向后移
            C[k] = A[i];
            i++;
        }
        else {
            C[k] = B[j];
            j++;
        }
    }
    cout << C[len - 1];
}

(3)数组指针后移(本质上和2一样,都是控制指针后移)

int GetMidNum(int A[], int B[], int len) {
    int count = 0, i, j, res;
    while (i < len && j < len && count < len) {
        if (A[i] < B[j]) {
            i++;
            res = A[i];
        }
        else {
            j++;
            res = B[j];
        }
        count++;
    }
    cout << res;
}
int GetMidNum(int A[], int B[], int len) {
    int i, j, k;
    for (k = 1, i = 0, j = 0; k < n; k++) {    //一共移动n - 1次
        if (A[i] < B[j]) i++;
        else j++;
    }
    cout << min(A[i], B[j]);    //输出A和B数组中当前元素的较小值
}

6.1.3.(2013) ffef097f69df4176bec17427445a80d9.png

(1)枚举:逐个元素判断(两层循环)

void MainNum(int A[], int n) {
    int i, j, count;
    for (i = 0; i < n; i++) {
        for (j = 0, count = 0; j < n; j++) {
            if (A[j] == A[i]) count ++;    //当前A[j]等于A[i],出现次数+1
        }
        if (count > n / 2) {
            cout << A[i];    //A[i]出现次数满足主元素要求,输出A[i]
            return;    //结束
        }
    }
    cout << -1;    //没有主元素,输出-1
    return;
}

(2)快速排序:

int Partation(int arr[], int low, int high) {
    随机选定数组下标low - high之间的元素和arr[low]对调    //快排优化
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) high--;
        arr[low] = arr[high];
        while (low < high && arr[low] <pivot) low++;
        arr[high] = arr[low;
    }
    arr[low] = pivot;
    return low;
}
void QuickSort(int arr[], int low, int high) {    //快速排序
    if (low < high) {
        int pivotPos = Partation(arr, low, high);
        QuickSort(arr, low, pivotPos - 1);
        QuickSort(arr, pivotPos + 1, high);
    }
}
int MainNum(int arr[], int n) {
    //count标记当前元素的出现次数,current记录当前元素
    int i, current = arr[0], count = 1;    
    for (int i = 1; i < n; i++) {    //遍历数组
        if (arr[i] == current) count ++;    //当前元素和current相同,出现次数 + 1
        else {    //当前元素和current不同,用当前元素替换current,并且出现次数归1
            current = A[i];
            count = 1;
        }
        if (count > n / 2) return current;    //出现次数大于>n/2,则current为主元素
    }
    return -1;    //没有主元素,返回-1
}

(3)动态规划:空间换时间,A出现的元素范围是正整数且<n,申请一个长度为n的数组,

第一遍遍历A数组记录每个元素其值出现的次数:设A中出现i,则count[i]++

第二遍遍历count数组,找是否有元素的值 > n/2,即A中出现次数 > n/2

int GetMainNum(int A[], int n) {
    int *count = (int*)malloc(sizeof(int) * n);
    memset(count, 0 , sizeof(int) * n);
    //遍历数组,将当前元素的值作为下标在count中对应元素+1
    for (int i = 0; i < n; i++) count[A[i]]++;
    //count[i]元素的值即i在A中出现的次数
    for (int i = 0; i < n; i++) {
        if (count[i] > n / 2) return i;    //i出现次数>n/2,i为主元素
    }
    return -1;
}

6.1.4.(2016)8b25a2ebcd2942dd897775fb82ffa276.png

快速排序:先对数组进行排序即满足需求(向下取整,即数组个数为奇数时,右大左小)

int Partation(int arr[], int low, int high) {
    随机选择一个数组下标为low - high的元素和arr[low]交换    //快排优化
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) high--;
        arr[low] = arr[high];
        while (low < high && arr[low] < pivot) low++;
        arr[high] = arr[low];
    }
    arr[low] = pivot;
    return low;
}
void QuickSort(int arr[], int low, int high){
    if (low < high) {
        int pivotPos = Partation(arr, low , high);
        QuickSort(arr, low, pivotPos - 1);
        QuickSort(arr, pivotPos + 1, high);
    }
}
void Divid(int arr[], int n){
    QuickSort(arr, 0, n - 1);    //快速排序
    for (int i = 0; i < n / 2; i++) cout << arr[i] << endl;    //输出子集A1
    for (int i = n / 2; i < n; i++) cout << arr[i] << endl;    //输出子集A2
}

6.1.5.(2018)c304e33e64b74b8c962330749a93abc5.png

(1)快速排序

int Partation(int arr[], int low,int high) {
    随机选择一个数组下标为low - high之间的元素和arr[low]交换    //快排优化
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) high--;
        arr[low] = arr[high];
        while (low < high && arr[low] < pivot) low--;
        arr[high] = arr[low];
    }
    arr[low] = pivot;
    return low;
}
void QuickSort(int arr[], int low, int high) {
    if (low < high) {
        int pivotPos = Partation(arr, low, high);
        QuickSort(arr, low, pivotPos - 1);
        QuickSort(arr, pivotPos + 1, high);
    }
}
int GetNum(int arr[], int n) {
    QuickSort(arr, 0, n - 1);    //将数组排序成有序
    int i, j;
    while (arr[i] <= 0 && i < n) i++;
    if (i == n) return 1;    //数组中的没有正数
    if (arr[i] != 1) return 1;    //此时arr[i]为数组中最小正整数
    //如果不是1,则1是未出现的最小正整数
    else {    //arr[i]为1,找到第一个正数间断点
        j = i + 1; 
        while (j < n && arr[j] != arr[j - 1] && arr[j] != arr[j - 1] + 1);
        return arr[j - 1] + 1;    //返回上一个元素+ 1的值
    }
}

(2)空间换时间

int MinNum(int arr[], int n) {
    int *count = (int*)malloc(sizeof(int) * (n + 1));
    memset(count, 0, sizeof(int) * (n + 1));
    int i;
    //遍历数组,当前元素大于0,则在count数组以该元素为数组下标的元素自增1
    for (i = 0; i < n; i++) if (arr[i] > 0) count[arr[i]]++;
    //count数组元素的值即该下标在arr数组中出现的次数,返回第一个为0的下标
    for (i = 1; i < n + 1; i++) if (count[i] == 0) return i;
}

6.1.6.(2020)70f3d649837d42a1a3f19655b005e605.png

int GetDis(int a, int b){
    int c = a - b;
    if (c >= 0) return c;
    else return -c;
}
int MinDis(int A[], int B[], int C[], int lenA, int lenB, int lenC){
    int i, j, k, temp;
    int min = MAX_INT;    //将min初始化为INT类型的最大值
    for (i = 0; i < lenA; i++){
        for (j = 0; j < lenB; j++){
            for (k = 0; k < lenC; k++){
                //计算三个数组当前元素的距离
                temp = GetDis(A[i], B[j]) + GetDis(A[i], C[k]) + GetDis(B[j], C[k]);
                //更新min
                if (temp < min) min = temp;
            }
        }
    }
    return min;
}

6.2.链表

6.2.1.(2009)7c4d31edab9d4cedb94429fae6c95f3d.png

(1)前后指针

int GetK(LNode *L, int k){
    LNode *p = L, *q = L;
    for (int i = 1; i < k; i++) p = p->link;    //p向前移动k - 1个结点
    while(p->link) {    //p和q同步移动,p移动至链表最后一个结点时,q就是倒数第k个结点
        p = p->link;
        q = q->link;
    }
    return q->data;    //返回q的data
}

(2)用数组保存每个结点的值

int GetK(LNode *L, int k){    
    int len = 0;    
    LNode *p = L;
    while (p) {    //遍历链表得到链表长度
        p = p->link;
        len++;
    }
    int *arr = (int*)malloc(sizeof(int) * len);    //申请和链表长度相同的数组
    int i = 0;
    p = L;
    while (p) {    //遍历链表,保存每个结点的值到数组中
        arr[i++] = p->data;
        p = p->link;
    }
    cout << arr[n - k];    //输出倒数第k个结点
}

(3)遍历数组两次,第一次得到数组的长度,第二次移动到倒数第k个

int ans(LNode *L, int k){
    int len = 0;
    LNode *p = L;
    while (p) {    //第一遍循环得到链表长度
        p = p->next;
        len++;
    }
    p = L;    //p重新指向头结点
    count = n - k + 1;
    while (count > 0) p = p->next;
    cout << p->data;
}


相关文章
|
2月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
68 1
|
2月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
160 4
|
11天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
34 2
|
27天前
|
存储 运维 监控
探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
57 20
|
2月前
|
存储 算法 搜索推荐
Python 中数据结构和算法的关系
数据结构是算法的载体,算法是对数据结构的操作和运用。它们共同构成了计算机程序的核心,对于提高程序的质量和性能具有至关重要的作用
|
2月前
|
数据采集 存储 算法
Python 中的数据结构和算法优化策略
Python中的数据结构和算法如何进行优化?
|
2月前
|
算法
数据结构之路由表查找算法(深度优先搜索和宽度优先搜索)
在网络通信中,路由表用于指导数据包的传输路径。本文介绍了两种常用的路由表查找算法——深度优先算法(DFS)和宽度优先算法(BFS)。DFS使用栈实现,适合路径问题;BFS使用队列,保证找到最短路径。两者均能有效查找路由信息,但适用场景不同,需根据具体需求选择。文中还提供了这两种算法的核心代码及测试结果,验证了算法的有效性。
131 23
|
2月前
|
算法
数据结构之蜜蜂算法
蜜蜂算法是一种受蜜蜂觅食行为启发的优化算法,通过模拟蜜蜂的群体智能来解决优化问题。本文介绍了蜜蜂算法的基本原理、数据结构设计、核心代码实现及算法优缺点。算法通过迭代更新蜜蜂位置,逐步优化适应度,最终找到问题的最优解。代码实现了单链表结构,用于管理蜜蜂节点,并通过适应度计算、节点移动等操作实现算法的核心功能。蜜蜂算法具有全局寻优能力强、参数设置简单等优点,但也存在对初始化参数敏感、计算复杂度高等缺点。
74 20
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
80 1
|
2月前
|
机器学习/深度学习 算法 C++
数据结构之鲸鱼算法
鲸鱼算法(Whale Optimization Algorithm,WOA)是由伊朗研究员Seyedali Mirjalili于2016年提出的一种基于群体智能的全局优化算法,灵感源自鲸鱼捕食时的群体协作行为。该算法通过模拟鲸鱼的围捕猎物和喷出气泡网的行为,结合全局搜索和局部搜索策略,有效解决了复杂问题的优化需求。其应用广泛,涵盖函数优化、机器学习、图像处理等领域。鲸鱼算法以其简单直观的特点,成为初学者友好型的优化工具,但同时也存在参数敏感、可能陷入局部最优等问题。提供的C++代码示例展示了算法的基本实现和运行过程。
78 0

热门文章

最新文章