12
返回列表 发新帖
楼主: Neroldy
跳转到指定楼层
上一主题 下一主题
收起左侧

[动态规划] 发一道碰到的数组题

🔗
Gary.W 2019-6-18 04:35:52 | 只看该作者
全局:
用heap 可以优化到O(nlogk)
基本思路就是如果对于一个全为S开头的子串 "S......S", 必然是先把从最左边(或最右边)开始把若干个S(<=3) 变为 . 有些位置可以把转化3个S, 有些位置只能转化1或2个S, 我们总共就只能做K 次操作。 所以就选top k 个位置。 太懒了,就先贴一个nlogn 的代码吧, 如果限制heap的size为K, 那么负责度就是 nlogk.

  1. #include <iostream>
  2. #include <queue>
  3. #include <string>

  4. int solve(string s, int k) {
  5.     priority_queue<int> q;
  6.     int idx = 0;
  7.     int ret = 0;
  8.     while(idx < s.size()) {
  9.         if(s[idx] == '.') {
  10.             ret++;
  11.             idx++;
  12.         }
  13.         else {
  14.             int len = 0;
  15.             while(idx + len < s.size() && s[idx + len] == 'S' && len <= 2)
  16.                 len++;
  17.             q.push(len);
  18.             idx += len;
  19.         }
  20.     }
  21.     while(k != 0 && !q.empty()) {
  22.         ret += q.top();
  23.         q.pop();
  24.         k--;
  25.     }
  26.     return ret;
  27. };

  28. string t = "SSSSSS.SSS..SSS.SS.S.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS.SS.SSSSSSSSSSSSSSSSSSS.SSSSSS.SSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSS.S.SSS.SSSSSS.SSSSSSSSSSS.SSSSSSSSSSSSS.SSSSSSS.S.SSSS.SSSSSSSSSSSS.SSSSSSSSSSSSSSSS.SSS.S.SS.SSSSSSS.SSSSSSSS.SSS.S.";
  29. int main() {
  30.     cout << solve(t, 23) << endl;
  31.     return 0;
  32. }
复制代码

评分

参与人数 1大米 +2 收起 理由
Neroldy + 2 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
 楼主| Neroldy 2019-6-18 09:28:38 | 只看该作者
全局:
337845818 发表于 2019-6-18 00:41
https://leetcode.com/problems/max-consecutive-ones-iii/

补充内容 (2019-6-18 00:45):

哥们你这是我一开始的想法,不过很遗憾应该是错的。
比如
6 2
S.SSSS
按照你的做法答案是5,正确答案是6。
回复

使用道具 举报

🔗
 楼主| Neroldy 2019-6-18 09:39:52 | 只看该作者
全局:
Gary.W 发表于 2019-6-18 04:35
用heap 可以优化到O(nlogk)
基本思路就是如果对于一个全为S开头的子串 "S......S", 必然是先把从最左边 ...

哥们你试试这个?
6 2
S.SSSS
6
我这边测的是输出的是5
回复

使用道具 举报

🔗
seeker丶 2019-6-18 09:47:43 | 只看该作者
全局:
来贴代码了,昨天睡觉的时候优化到了O(n),其实证明链表里每次断裂后不会产生新的连续3个S(或者1,2个s,如果当前在检查相应的长度)即可,每遍都从前往后扫一遍就可以啦。

  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <iterator>
  5. #include <algorithm>
  6. #include <list>
  7. using namespace std;

  8. int solve(string s,int n,int k)
  9. {
  10.     list<int> l;
  11.     int res = 0;
  12.     for(auto i:s){
  13.         if(i=='.') // . converts to 1 and S converts to 0
  14.         {
  15.             res++;
  16.             l.push_back(0);
  17.         }else
  18.             l.push_back(1);
  19.     }
  20.     for(int curCheck = 3; curCheck>=1 && k>0; curCheck--)
  21.     {
  22.         if(l.size()<3)
  23.             break;
  24.         auto i=l.begin(), j=i;
  25.         int windowSum = *(i++);
  26.         windowSum += *(i++);
  27.         while(i!=l.end())
  28.         {
  29.             windowSum += *(i++);
  30.             if(windowSum == curCheck)
  31.             {
  32.                 res += curCheck;
  33.                 k--;
  34.                 if(k == 0)
  35.                     break;
  36.                 l.erase(j++);
  37.                 l.erase(j++);
  38.                 l.erase(j++);
  39.                 windowSum =0;
  40.                 if(i == l.end())
  41.                     break;
  42.                 windowSum += *(i++);
  43.                 if(i == l.end())
  44.                     break;
  45.                 windowSum += *(i++);
  46.                 continue;
  47.             }
  48.             windowSum -= *(j++);
  49.         }
  50.     }
  51.    
  52.     return res;
  53. }

  54. int main(int argc, const char * argv[]) {
  55.     cout<<solve("SS.S...S....SS..S..S.S.S...SS...SSS..SS.SS.SSSSS...S.S.S...S......S",67,4)<<endl;
  56.     cout<<solve(".S.....SSSSS.SSSS...SS.SSS.SS",29,2)<<endl;
  57.     cout<<solve(".S...SSS.SSS..SSSS.SSSSS.SS.S.SS.SS.SSSSSSS.SS...SS.S.SSS.SS.S.SS..S..S.SSS.SS.",79,6)<<endl;
  58.     cout<<solve("SSSSSS.SSS..SSS.SS.S.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS.SS.SSSSSSSSSSSSSSSSSSS.SSSSSS.SSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSS.S.SSS.SSSSSS.SSSSSSSSSSS.SSSSSSSSSSSSS.SSSSSSS.S.SSSS.SSSSSSSSSSSS.SSSSSSSSSSSSSSSS.SSS.S.SS.SSSSSSS.SSSSSSSS.SSS.S.",276,23)<<endl;
  59.     return 0;
  60. }
复制代码

评分

参与人数 1大米 +2 收起 理由
Neroldy + 2 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
Gary.W 2019-6-18 10:39:46 来自APP | 只看该作者
全局:
Neroldy 发表于 2019/06/18 09:39:52


哥们你试试这个?
6 2
S.SSSS
6
我这边测的是输出的是5

这个case 不应该是5吗
回复

使用道具 举报

🔗
Gary.W 2019-6-18 10:41:20 来自APP | 只看该作者
全局:
Gary.W 发表于 2019/06/18 10:39:46


这个case 不应该是5吗

噗, 溜了溜了
回复

使用道具 举报

🔗
hyn 2019-6-28 22:55:05 | 只看该作者
全局:
@seeker丶 的代码是没问题的,但是证明应该不对啊,比如
6 2
S.SSSS
其实正确的原因是删除链表节点后,后续节点自动向前补充,从而使得最初的选择是“可移动的”,但是在证明中没体现这一点。
回复

使用道具 举报

全局:
hyn 发表于 2019/06/28 22:55:05
@seeker丶 的代码是没问题的,但是证明应该不对啊,比如
6 2
S.SSSS
其实正确的原因是删除链表节点后,后续节点自动向前补充,从而使得最初的选择是“可移动的”,但是在证明中没体现这一...

这个我觉得是用链表的基本原理了,我觉得读者应该能想明白之所以用链表就是这样的思想,但是仅有这一点不能保证贪心就最优啊,所以正确性的重点还要考虑重叠情况。

换句话说,我不用考虑相对别人的方法为什么“正确”,而要考虑相对链表方法中可能存在的错误为什么“正确”而进行证明
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表