三条面经题目

第一题:有m个餐厅,其中抽n个改造成停车场,使每个餐厅到最近的停车场距离之和最小

定义:dp[i][j]表示前i个餐厅有j个停车场的

初始:cost[k][i]表示第k个餐厅到第i个餐厅只有1个停车场服务时的最小矩离和
dp[i][1]的就是cost[1][i],注意只有1个停车场时一定是取中位数的位置

递堆:dp[i][j]=min(dp[i][j],dp[k-1][j-1]+cost[k][i])
前i个餐厅有j个停车场相当于前k-1个餐厅有j-1个停车场,然后第k到i个餐厅有1个停车场

优化:四边形不等式优化,对K的遍历可以加速,由o(mmn)降为o(mn)

第二题:找出数组中的最长子区间,和为给定值k

例:[3,-2,-4,0,6,1],k=0
解:开map<int,int>,Key是前缀和,val是下标,先压入<0,-1>,表示下标-1没有数时和就是0
到下标0位置,由于当前sum是3,要找区间和是0,则要找map有没有前缀和是3-0=3,但是没有故跳过,压入<3,0>
到下标1位置,由于当前sum是1,要找区间和是0,则要找map有没有前缀和是1-0=1,但是没有故跳过,压入<1,1>
到下标2位置,由于当前sum是-3,要找区间和是0,则要找map有没有前缀和是-3-0=-3,但是没有故跳过,压入<-3,2>
到下标3位置,由于当前sum是-3,要找区间和是0,则要找map有没有前缀和是-3-0=-3,有<-3,2>,得到区间[3,3],不用压入
到下标4位置,由于当前sum是3,要找区间和是0,则要找map有没有前缀和是3-0=3,有<3,0>,得到区间[1,4],不用压入
以下标5位置,由于当前sum是4,要找区间和是0,则要找map有没有前缀和是4-0=4,但是没有故跳过,压入<4,5>
结束,获得最长子区间[1,4]

补充解释为何下标3(下标4同理)不用压入<3,3>:因为前面有<3,0>,取下标较小的就能获得较长的区间

第三题:找到数组中的最长子区间,和小于等于给定值k

例:[3,-2,-4,0,6],k=-2
解:开map<int,int>,Key是前缀和,val是下标,先压入<0,-1>,表示下标-1没有数时和就是0
到下标0位置,由于当前sum是3,要找区间和小于等于-2,则要找map有没有前缀和是大于等于3-(-2)=5,但是没有故跳过,压入<3,0>
到下标1位置,由于当前sum是1,要找区间和小于等于-2,则要找map有没有前缀和是大于等于1-(-2)=3,有<3,0>,找到区间[1,1],不用压入<1,1>【优化,见解释】
到下标2位置,由于当前sum是-3,要找区间和小于等于-2,则要找map有没有前缀和是大于等于-3-(-2)=-1,有<3,0>与<0,-1>,找到区间[0,2],不用压入<-3,2>
到下标3位置,由于当前sum是-3,要找区间和小于等于-2,则要找map有没有前缀和是大于等于-3-(-2)=-1,有<3,0>与<0,-1>,找到区间[0,3],不用压入<-3,3>
到下标4位置,由于当前sum是3,要找区间和小于等于-2,则要找map有没有前缀和是大于等于3-(-2)=5,但是没有故跳过,不用压入,因为<3,0>比<3,4>有更小下标
结束,获得最长子区间[0,3]

补充解释为何不用压入<1,1>:因为对比<3,0>,设现在要找map中找的前缀和值是x,若1大于等于x,则3必然大于等于x,而<3,0>有更优的下标0,所以不用压入<1,1>
同理,<-3,2>也不如<3,0>优,因此可以得到结论,压入map的前缀和值一定是单调递增的,因为下标肯定不断增,前缀和若是有比以前小的,在选择时一定不是最优

猜你喜欢

转载自blog.csdn.net/cj1064789374/article/details/106074802