算法第四章实验报告
1.算法分析
1.1 问题描述
题目:删数问题
给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最小的删数方案。如果数字最前面有0不输出。
输入格式:第 1 行是1 个正整数 a。第 2 行是正整数k。
输出格式:输出最小数。
1.2算法描述
贪心选择性质
题目要求设计一个算法,找出剩下数字组成的新数最小的删数方案。
ps:如果数字最前面有0不输出;数字顺序不变。
因此,我没可以将问题进行拆分,每一次删数后新产生的数字均是最小数。
贪心策略:从最左边(a[0]
)开始遍历,将前后两个数字进行比较,当前面的数字大于后面的数字的时候,删掉前面的数字a[i]
,并将删除数字右边的数字全部向左移一位( a[i] = a[i + 1]
)。
补充:跳过首字0
1 int i = 0; 2 while(i < len && a[i] == '0') //判断数字是否以0开头 3 { 4 i++; //跳过0,然后再开始输出 5 }
2.代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 6 int main() 7 { 8 string a; 9 int n; 10 cin >> a; 11 cin >> n; 12 13 int len; 14 len = a.size(); //求数组长度 15 16 int j = 0; 17 for(int k = 0; k < n; k++) //循环条件:删除n个数 18 { 19 for(int i = 0; i < len - 1; i++) 20 { 21 if(a[i] > a[i+1]) //如果前面的数大于后面的数,应该将前面的数删除 22 { 23 for(int t = i; t < len - 1; t++ ) 24 { 25 a[t] = a[t+1]; 26 } 27 break; //退出当前循环,开始寻找下一个删除的数 28 } 29 } 30 len--; 31 } 32 33 int i = 0; 34 while(i < len && a[i] == '0') //判断数字是否以0开头 35 { 36 i++; //跳过0,然后再开始输出 37 } 38 39 if(i == len) //全部数字都是0 40 { 41 cout << "0"; 42 } 43 else 44 { 45 for(int j = i; j < len; j++) //跳过0再开始输出 46 { 47 cout << a[j]; 48 } 49 } 50 }
3.时间复杂度分析
时间复杂度:O(nk) ----n指删除的数字个数,k指的是数组长度。
解释:每删除一个数字,都需要遍历整个数组找到需要删除的数,即为删除个数*数组长度
4.对贪心算法的理解
贪心算法的主要步骤:
-
建立模型描述问题
-
将求解问题分解为若干子问题
-
找到子问题的局部最优解(运用贪心思想,找到合适的贪心策略)
-
将局部最优解合并为最终答案
-
不能保证求得最优解
-
不能求最值问题
-
只能求满足某些约束条件的可行解的范围(求解问题必须有限定范围)