目录
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循环对子序列进行遍历,找到比基准数个数多的数就更新。问题的难点就在于子问题递归中出现的种种问题,比如通过指针或者数组在函数之间正确传递值。这是对于该问题的简要分析。