编程语言
首页 > 编程语言> > 算法第四章上机实践报告

算法第四章上机实践报告

作者:互联网

1.实践题目:4-2删数问题

2.问题描述

  给定一串数字和删去位数n,设计算法找出原串删去n位后剩下数字组成新数最小的删数方案

  输出要求 删除新数的前导0 全0时输出0

3.算法描述

  数字串原长len位,删去n位

  因此目标数位长len-n位

  定义两个指针start,end,每次在原数组arr[start,end]范围内取最小值作为目标数的第1,2,..len-n位

  初始时start=0,end=n;因为第一次(找目标数最高位)的过程要保证后面至少有len-n-1个数字作为目标数的[2,len-n]位,所以最高位数字的可选范围是原串中首n+1位数字

  每次遍历[start,end],记录最小值的大小min及下标mark,start指向下标的下一位,end后移一位(保证第i次取数 原串后仍有len-n-i个数字填入新数)

  贪心策略:每次在可选范围内选择最小的数作为新数高位

  反证法证明贪心选择和最优子结构性质:

    样例给出6位正整数178543,去掉其中任意4个数字

    即最优解是一个包含两个数字(按在原串中的顺序)的新数,对于新数的最高位/首数字,按照贪心策略找到的数字是1;

    设最优解XY,且首数字X不等于1(即最优解不包含数字1),则数字1小于(现在假定的)最优解XY的首数字X,包含数字1的解组成的新数一定比XY小,数字1可以替代数字X,与假设前提“XY是最优解”矛盾,故证明 该问题的最优解包含其子问题的最优解(从左往右每一位上的数字取最小值 ‘局部最优’),即具有最优子结构性质

 

4.算法时间及空间复杂度分析

while(end<len){

        int min_=0x3f3f3f3f;

        for(int i=start;i<=end;i++){

            if(arr[i]<min_){

                min_=arr[i];

                mark=i;

            }

        }

        ans[cnt++]=min_;

        start=mark+1;

        end++;

    }

 

  里层for循环遍历的最长跨度是n+1,每次确定一个数字,共执行len-n次(len>=n)因此时间复杂度是O(n^2)//小于O(n^2)

  只使用了变量min_记录每次循环找到的局部最优解,所以空间复杂度是O(1)

5.心得体会

  贪心策略完全是思维超好的队友小姐姐想的!回去后看网上的题解觉得这个策略比题解的每次遍历维护一个升序数组 的策略要更好理解和敲。上机时因为我的写法过于沙雕而没有过测试点90/110,希望以后做题的时候清醒点!

标签:新数,end,数字,上机,len,start,算法,最优,第四章
来源: https://www.cnblogs.com/biekanle/p/11870047.html