4-1 程序存储问题
有限空间中放最多的程序,很容易就可以想到优先放最小的程序,就会得到最大数量。
sort(a, a + n); //sum为存储空间大小 for(int i = 0; i < n; i++) { sum -= a[i]; if(sum < 0) { cout << i; break; } if(sum == 0) { cout << i + 1; break; } }
时间复杂度为 O(n * log n)
4-2 删数问题
给定一串数字,题目要求删掉 t 个数字(删掉后先后关系不变),问如何删才能取得最小值。
可以从另一个问题引申出求解思路
问题:假设有 x 个数字可以任意排列,如何才能让其取值最小?
答案:小的数放在高位,大的数放在低位,使他由高位到低位单调递增
此题原理相同,要使得得到的数最小,就每次删掉逆序的数就可以了。
while(t--) { //t为要删除数字的个数 int cnt = 0;//记录要删掉的数的下标 for(int i = 1; i < a.size(); i++) { if(a[i] < a[i-1]) { cnt = i - 1; break; } } a.erase(cnt, 1); //删除选中数 if(a.size()==0) { cout << 0; return 0; } //删掉前导0 while(a.size() > 1 && a[0]=='0') { a.erase(0, 1); } } //因为直接以字符串读取一行会多出一个空格,所以先判断一下是不是数字 for(int i = 0; i < a.size(); i++) if(isdigit(a[i])) cout << a[i];
假设有 n 位数字,时间复杂度为 O(t * n)
4 - 3 最优和并问题
用到哈夫曼树,用大根堆,小根堆能快速解决,优先最大的或最小的两个,没什么难点。
时间复杂度,优先队列插入单个数是 log n 的,n 个数,所以是 O(n * log n) 的。
总结:贪心算法没有固定的套路,有时候证明也很难,但比较符合人的直觉,很多时候可以先猜想再通过程序去验证。