题解 | #牛牛摆放花#

牛牛摆放花

http://www.nowcoder.com/practice/9a11f48530d94188b430db9afe19d20e

思路

题目分析

  1. 题目给出数组的大小,同时给出了一个数组
  2. 题目规定数组中元素表示花高
  3. 题目的数组围成一圈,相邻元素的差值最大值作为这个圈的丑陋值
  4. 我们要合理排序这个圈中的元素,使这个圈的丑陋值最小
  5. 返回这个圈的最小丑陋值
  • 方法一:暴力(超时)
    • 枚举出来所有的排序方案
    • 逐个计算出每个圈的丑陋值
    • 选出最小的丑陋值
    • 时间代价巨大
  • 方法二:贪心数学性质
    • 我们可以想到这个圈在数组的表现形式应该是先递增,后递减
    • 因此排序很重要
    • 排序后,将奇数位的元素统一移到前面,偶数位的元素统一移到后面
      • 奇偶交替一前一后向中间逼近,使得中间的值是最大的
      • 这样做的原因是我们需要丑陋值最小,而丑陋值是和相邻元素之间的差值有关
      • 我们只有将递增顺序的全序列一奇一偶地拆分重新排列到数组首尾,才能保证最新的序列相邻元素之间的差值被降到最小
      • 否则按照其他方法排列的新序列,丑陋值这个差值只能大于上述安排方案
    • 这样贪心地形成了先递增后递减的序列
    • 计算出来的圈丑陋值就是最小的

贪心证明(给看不懂上面文字描述的同学具体推理一下)

  • 假设存在一组递增的序列a1,a2,a3,...,ana_1,a_2,a_3,...,a_na1,a2,a3,...,an,我们将其按照上述贪心策略进行安排之后会形成的序列为a1,a3...,an,...,a4,a2a_1,a_3...,a_n,...,a_4,a_2a1,a3...,an,...,a4,a2,因此此时丑陋值我们可以计算为max(a1a2,ai+2ai,anan1(nn))max(|a_1-a_2|, |a_{i+2}-a_{i}|, |a_{n}-a_{n-1}|(如果n为偶数,n为奇数则无此项))max(a1a2,ai+2ai,anan1(nn))
  • 根据题意,按照这种方法排序的结果我们将其视作一个环状序列,首尾要相接,因此如果这个排列的整体前后错位了也是不影响的。
  • 我们使用反证法证明结论
  • 假设如果我们不按照此顺序排列(环状呈现的结果不同),则必定会出现有相邻的两个元素存在aiaj(ij>2)|a_{i}-a_{j}|(i-j>2)aiaj(ij>2)ai+2ai|a_{i+2}-a_{i}|ai+2ai要大,因此丑陋值一定比上面的maxmaxmax计算出来的大,因此得证

方法一:暴力(超时)

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回按照这些花排成一个圆的序列中最小的“丑陋度”
     * @param n int整型 花的数量
     * @param array int整型vector 花的高度数组
     * @return int整型
     */
    int arrangeFlowers(int n, vector<int>& array) {
        // write code here
        int res = INT_MAX;
        while(next_permutation(array.begin(), array.end())) {    // 遍历所有的排序方案
            int val = abs(array[0] - array[n-1]);                // 围成一圈后首位元素要计算一次
            for(int i = 0; i < n-1; i++) val = max(val, abs(array[i+1] - array[i])); // 其他元素相邻高度差也要计算
            res = min(res, val);    // 从每一躺的丑陋值中选出最小的丑陋值
        }
        return res;
    }
};

复杂度分析

  • 时间复杂度:O(N!)O(N!)O(N!),所有的的排序方案全部要进行
  • 空间复杂度:O(1)O(1)O(1),使用了常量级别的空间大小

方法二:贪心数学性质

alt

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回按照这些花排成一个圆的序列中最小的“丑陋度”
     * @param n int整型 花的数量
     * @param array int整型vector 花的高度数组
     * @return int整型
     */
    int arrangeFlowers(int n, vector<int>& array) {
        // write code here
        int cnt[n];
        sort(array.begin(), array.end());            // 对原数组排序
        int l = 0;                                   // 标记左侧指针
        int r = n-1;                                 // 标记右侧指针
        for(int i = 0; i < n; i++) {                 // 对排序后的数据遍历
            if(i % 2 == 0) {                         // 偶数位置的数字重新放到最前面
                cnt[l++] = array[i];
            }
            else {                                   // 奇数位置的数字重新放到最后面
                cnt[r--] = array[i];
            }
        }
        
        int res = 0;
        for(int i = 0; i < n - 1; i++) {
            res = max(res, abs(cnt[i+1] - cnt[i]));    // 重新统计相邻元素高低岔开的最大高度值
        }
        return res;
    }
};

复杂度分析

  • 时间复杂度:O(NlogN)O(NlogN)O(NlogN),主要时间代价消耗在排序上
  • 空间复杂度:O(N)O(N)O(N),使用了一个新的一维数组,量级和原数组大小一致
不会做题写的题解 文章被收录于专栏

哎呀我好笨呀,一不小心又不会了一道题

全部评论

相关推荐

点赞 评论 收藏
分享
06-10 23:36
已编辑
首都经济贸易大学 C++
点赞 评论 收藏
分享
来个大佬救一下,为上投了都是石沉大海了,没实习经历的话怕秋招直接进不了面。什么实习这么难找,基本
心态爆炸了:现在正式的岗位都少,实习基本不咋招的,除了大厂,中小企业其实没那么多岗位需求,就算是有,大多都是招一两个廉价劳动力,同时,他们也会希望你一来就能干活的,没时间培训你,就让你了解公司的项目,你了解完就可以开始干活。再者是,很多低质量的实习其实用处没有那么大的。我去年也是找实习找到破防,最后去了一家深圳的小公司实习,工作对我来说很简单,甚至不如我在学校做的项目,秋招的时候,这段实习经历也并没有帮上什么忙,投递简历,依旧非常低的回复率。低回复率是常态,尤其是找实习,找不到,那就把重心放在优化自己的简历和项目,多看八股文,锻炼自己的面试能力,多看别人的面经,自己模拟面试,等秋招的时候,只要有那么寥寥几次,好好抓住那几次机会。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务