题解 | #牛牛摆放花#

牛牛摆放花

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),使用了一个新的一维数组,量级和原数组大小一致
不会做题写的题解 文章被收录于专栏

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

全部评论

相关推荐

Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
10-15 16:27
门头沟学院 C++
LeoMoon:建议问一下是不是你给他付钱😅😅
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务