目录

1.题目概述:

2.题目解析:

3.题目代码:

4.样例展示:

5.题目总结:


1.题目概述:

给定一个整数序列,每个元素出现的次数称为重数,重数最大的数据元素称为众数。设计算法对递增有序序列a求众数。例如: a={1,2,2,3,5},则a的众数是2,其重数为3。


2.题目解析:

大致思想:将要求解的较大规模的问题分割成k个更小规模的子问题进行求解,若规模仍不够小就再分,直到规模足够小且很容易求解为止,最后自底向上逐步求解合并为原来的解。

—-分治策略


对应的解题步骤:

(1)解决小规模的问题

(2)分解问题

(3)递归的解各子问

(4)将各子问题的解合并为原问题的解


分治策略适用的条件:

(1)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;

(2)利用该问题分解出的子问题的解可以合并为该问题的解;

(3)该问题的规模缩小到一定的程度就可以容易地解决;

(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。


本题策略:

(1)将这n个数分成大致相同的两半,然后在每部分找到中间值,通过这个中间值在各自的那一半里找出最大值,再比较两个最大值从而得到原问题的解(规模可以缩小,具有最优子结构,子问题可以合并为原问题的解,子问题相互独立),当问题规模缩小到只有两个元素时,只需要一次就比较就可以得出答案(子问题求解容易),满足分治策略的4个适用条件。

(2)用数组a[]保存输入的n个数,low表示第一个数的下标,high表示最后一个数的下标, low==high作为结束条件,然后令mid表示low和high中间的那个数的下标,分解成子问题:low到mid之间找出左边的最大值left_max和子问题mid+1到high之间找出右边的最大值right_max,然后取二者中的大者,直到分解情况满足结束条件才结束。


3.题目代码:

#include void Middle();void getMode();int main(){    int Mode = 0, Mult = 0, *p, *q;    p = &Mode, q = &Mult;    int i, n;    printf("请输入整数序列中整数的个数:");    scanf("%d", &n);    int a[n];    printf("请输入整数序列:\n");    for (i = 0; i < n; i++)        scanf("%d", &a[i]);    getMode(p, q, a, n);    printf("众数:%d\n", Mode);    printf("重数:%d\n", Mult);    return 0;}void Middle(int a[], int n, int b[]) //确定左右界{    int i, mid = n / 2;        //取中间数字mid为界    for (i = 0; i <= mid; i++) //找左界        if (a[i] == a[mid])        {            b[0] = i;            break; //此时b[0]为左界        }    for (i = mid + 1; i  *Mult) //如果中间数字的个数大于现在的重数,则更新    {        *Mode = a[mid];        *Mult = tempNum;    }    if (b[0] + 1 > *Mult) //如果左边的个数>maxnum,则在左部开始搜索        getMode(Mode, Mult, a, b[0] + 1);    if (n - b[1] > *Mult) //如果右边的个数>maxnum,则在右部开始搜索        getMode(Mode, Mult, a + b[1], n - b[1]);}

4.样例展示:


5.题目总结:

对于该问题,找出最中间的数作为基准数,分成相等的两个子问题,对于子问题递归调用该算法进行解决,通过for循环对子序列进行遍历,找到比基准数个数多的数就更新。问题的难点就在于子问题递归中出现的种种问题,比如通过指针或者数组在函数之间正确传递值。这是对于该问题的简要分析。