《程序员面试金典(第6版)》面试题 10.11. 峰与谷(双指针,贪心思想)

news2024/9/22 23:30:21

题目描述

在一个整数数组中,“峰”是大于或等于相邻整数的元素,相应地,“谷”是小于或等于相邻整数的元素。例如,在数组{5, 8, 4, 2, 3, 4, 6}中,{8, 6}是峰, {5, 2}是谷。现在给定一个整数数组,将该数组按峰与谷的交替顺序排序。

示例:

  • 输入: [5, 3, 1, 2, 3]
  • 输出: [5, 1, 3, 2, 3]

提示:

  • nums.length <= 10000

解题思路与代码

这道题我对他的理解就是我要把它给我的数组里的元素排列成一个大一个小的模样。当然这道题的答案是不唯一的。你想怎么排就怎么排。第一个元素是波峰还是波谷都无所谓。

那我们就来看看我们可以写出多少种做法。

方法1,sort排序后 + 分割数组 + 用了额外的vector

  • 我这方法一写出来,就感觉有一点土味,不过无所谓,提交成功就行。

  • 首先把这个数组用sort函数从新排列一下,这个时候它就变成了一个有序数组,然后从数组中间将数组一分为二,分别存入两个新的数组中。聪明的大家肯定能知道我这一步是为啥,更聪明的同学可能知道了一种更好的方法。

  • 此时,原数组前半部分元素的数组记为n1,另一部分记为n2

  • 用一个while循环,每循环一次就重新替换原数组中的两个元素直到替换完毕

具体实现请看代码:

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        if(nums.empty()) return ;
        sort(nums.begin(),nums.end());
        int mid = (nums.size()) / 2;
        vector<int> n1 (nums.begin(),nums.begin() + mid);
        vector<int> n2 (nums.begin() + mid, nums.end());
        int p1 = 0;
        int p2 = 0;
        int i = 0;

        while(p1 < n1.size() && p2 < n2.size() ){
            nums[i] = n2[p2];
            ++i;
            ++p2;
            nums[i] = n1[p1];
            ++i;
            ++p1;
        }
        if(p2 < n2.size()){
            nums[i] = n2[p2];
        }

        return ;
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:

  • 排序:sort 函数的时间复杂度为 O(n*logn),其中 n 是数组 nums 的长度。
    创建两个子数组:这部分的时间复杂度为 O(n),因为需要遍历整个数组。
  • 合并子数组:这部分的时间复杂度也为 O(n),因为需要遍历两个子数组的长度之和。
  • 综上,整个算法的时间复杂度为 O(n*logn)。

空间复杂度:

  • 创建两个子数组 n1 和 n2:这部分的空间复杂度为 O(n),因为需要存储原数组的所有元素。
  • 其他变量的空间消耗可以忽略不计。
  • 综上,整个算法的空间复杂度为 O(n)。

方法2,对方法1的优化,使用双指针替代额外vector

首先,当数组元素的数量等于0,1,2时,原地返回

之后对数组的元素进行排序,排序后开始while循环

循环中用双指针分别指向数组的第2个和第3个元素,交换它们。

双指针分别加2,直到循环结束,返回

具体代码如下:

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        int size = nums.size();
        if(size == 0 || size == 1 || size == 2) return;
        sort(nums.begin(),nums.end());
        int left = 1;
        int right = 2;
        while(left < size  && right < size){
            swap(nums[left],nums[right]);
            left += 2;
            right += 2;
        }
        return ;
    }
};

在这里插入图片描述

复杂度分析

这个改进后的代码确实更简洁且高效。现在来分析一下新版本的时间复杂度和空间复杂度:

时间复杂度:

  • 排序:sort 函数的时间复杂度仍为 O(n*logn),其中 n 是数组 nums 的长度。
  • 交换元素:这部分的时间复杂度为 O(n),因为最多需要遍历整个数组。
  • 综上,整个算法的时间复杂度仍为 O(n*logn)。

空间复杂度:

  • 原地交换元素:这个改进后的实现不再需要额外的数组空间,所以空间复杂度降低。
    其他变量的空间消耗可以忽略不计。
  • 综上,整个算法的空间复杂度为 O(1)。

方法3,继续优化,不使用排序,直接在原数组上操作(用到了贪心的思想)

  • 对于这道题来说,时间复杂度最低的算法,也莫过于O(n)的算法了,也就是遍历一次原数组,就得出答案。

  • 说实话这道题平平无奇,我做完了才后知后觉我这道题其实采用了贪心的做法,因为贪心算法的思想经常与直观的解题思路相符。贪心算法的核心是在每一步都做出当前看起来最优的选择,而这种方法很容易与我们在解决问题时的自然直觉相吻合。

那我们来讲讲这道题我是如何做的吧:

  • 这个方法的思路是从数组的第二个元素开始,按照奇数索引位置为峰、偶数索引位置为谷的规律,依次遍历数组。
  • 在遍历过程中,如果当前元素与要求的峰谷规律不符,就与前一个元素交换位置。这样一来,整个数组就会按照峰谷交替的顺序排列。

具体的代码如下

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        for(int i = 1; i < nums.size(); ++i){
            if(i % 2 == 0){
                if(nums[i] > nums[i-1]) swap(nums[i],nums[i-1]);
            }else{
                if(nums[i] < nums[i-1]) swap(nums[i],nums[i-1]);
            }
        }
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

总结

这道题,我认为,总体上不难。考察了排序,双指针,与贪心思想。其实掌握其中任何一种知识点。对于解决这道题都不是太难的事情。

这道题贪心的解法,你可能要多想想才能想出来。不过也很好理解啦。

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/431493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络原理IP协议

hi,大家好,小魏又来了,我们已经认识了UDP,TCP,现在来认识一下位于网络层的协议,IP 认识IP地址 1.地址管理 2.路由选择 在之前的讲解中我们已经认识到了网络层的IP协议,负责寻路操作 IP地址&#xff08;Internet Protocol Address&#xff09;是指互联网协议地址&#xff0…

【Java版oj】day35年会抽奖、抄送列表

目录 一、年会抽奖 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 二、抄送列表 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 一、年会抽奖 …

C++ 命名空间 输入输出 缺省参数 引用 函数重载

在学习C之前&#xff0c;我们要先知道C和C是向上兼容的&#xff0c;也就是说&#xff0c;在cpp文件中既可以写入C的代码&#xff0c;也可以写C的代码&#xff0c;在日常编写代码中&#xff0c;经常会出现C和C混编的情况。 此博客都是在 C 的缺陷的基础之上 整理 C 中对其的优化…

PyTorch 之 强大的 hub 模块和搭建神经网络进行气温预测

文章目录一、强大的 hub 模块1. hub 模块的使用2. hub 模块的代码演示二、搭建神经网络进行气温预测1. 数据信息处理2. 数据图画绘制3. 构建网络模型4. 更简单的构建网络模型本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 一、强…

机器学习——回归与聚类算法

线性回归 广义的线性模型 不仅是自变量是一次方的是线性模型&#xff0c;参数是一次方的也是线性模型&#xff0c;比如&#xff1a; 总结&#xff1a;线性关系的一定是线性模型&#xff0c;线性模型的不一定是线性关系。 损失函数 优化损失 求解模型中的w&#xff0c;使得…

SeNet论文解读/总结

此文章为深度学习在计算机视觉领域的图片分类经典论文SeNet&#xff08;Squeeze-and-Excitation Networks&#xff09;论文总结。 此系列文章是非常适合深度学习领域的小白观看的图像分类经典论文。系列文章如下&#xff1a; AlexNet&#xff1a;AlexNet论文解读/总结_alexnet…

uniapp-搜索配置

自定义搜索组件 1.定义组件的 UI 结构: <template><!-- 通过属性绑定的形式&#xff0c;为 .my-search-container 盒子和 .my-search-box 盒子动态绑定 style 属性 --><view class"my-search-container" :style"{background-color: bgcolor}&q…

《花雕学AI》23:中文调教ChatGPT的秘诀:体验测试与通用案例,解锁无限有趣玩法!

引言&#xff1a; 你有没有想过和一台智能机器人聊天&#xff1f;你有没有想过让一台智能机器人为你创作诗歌、故事或歌曲&#xff1f;你有没有想过让一台智能机器人陪你玩游戏、学习或社交&#xff1f;如果你的答案是肯定的&#xff0c;那么你一定会对ChatGPT感兴趣。 ChatG…

Hystrix详解

前言 Hystrix基于Feign&#xff0c;想熟悉Hystrix&#xff0c;必须先熟悉Feign。 Feign&#xff08;简介和使用&#xff09;&#xff1a; Feign&#xff08;简介和使用&#xff09;_长头发的程序猿的博客-CSDN博客 Hystrix简介 hystrix对应的中文名字是“豪猪”&#xff0c…

Android开发 Camera2获取输出SurfaceTexture

目录 一、Camera2概述 1 Pipeline 2 CameraManager 3 CameraDevice 4 CameraCharacteristics 5 CameraCaptureSession 6 CaptureRequest 7 Surface 8 CaptureResult 三、Camera2的特性 1 Camera2 才支持的高级特性 2 Camera1 迁移到 Camera2 二、示例源码 一、Came…

Honggfuzz Linux arch_clone 源码阅读 (setjmp, clone)

Honggfuzz Linux arch_clone 源码阅读 &#xff08;setjmp, clone&#xff09; 阅读 Honggfuzz 系统架构相关源码&#xff0c;在创建子进程部分遇到了几个问题&#xff0c;经过研究得以解决&#xff0c;在此记录。 Source Code 代码节选自linux/arch.c&#xff0c;已添加注释&…

RabbitMq 消息可靠性问题(一) --- publisher发送时丢失

前言 消息从生产者发送到exchange, 再到 queue, 再到消费者。这个过程中有哪些有消息丢失的可能性呢&#xff1f; 发送时丢失&#xff1a; 生产者发送的消息未送达 exchange消息到达 exchange 后未到达 queue MQ 宕机&#xff0c;queue将消息丢失consumer 接收到消息后未消费…

聊聊如何运用JAVA注解处理器(APT)

什么是APT APT&#xff08;Annotation Processing Tool&#xff09;它是Java编译期注解处理器&#xff0c;它可以让开发人员在编译期对注解进行处理&#xff0c;通过APT可以获取到注解和被注解对象的相关信息&#xff0c;并根据这些信息在编译期按我们的需求生成java代码模板或…

基于DistFlow的含分布式电源配电网优化模型【IEEE39节点】(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

SpringBoot【基础篇】---- SSMP整合综合案例

SpringBoot【基础篇】---- SSMP整合综合案例1. 模块创建2. 实体类开发3. 数据层开发----基于CRUD查看MP运行日志查看 MP 的运行日志4. 数据层开发----分页功能制作5. 数据层开发----条件查询功能制作6. 业务层开发业务层快速开发7. 表现层开发8. 表现层消息一致性处理9. 前后端…

STC32G单片机内置ADC及应用编程

一 STC32G单片机内置ADC模块简介 STC32G单片机内部集成了一个12位高速ADC转换器&#xff0c;ADC的最高时钟频率为系统频率的1/2。其输入通道多达15个&#xff08;第15通道为专门测量内部1.19V参考信号源的通道&#xff09;&#xff0c;可分时切换使用。 STC15系列单片机内置AD…

AES加密

来源&#xff1a;链接: b站up主可厉害的土豆 &#xff08;据评论区说图片中有计算错误&#xff0c;但是过程是对的。只是了解过程问题不大&#xff0c;专门研究这一块的话自己可以看视频算一下&#xff09; 准备 首先&#xff0c;明文是固定长度 16字节 128位。 密钥长度可以…

C++语法(18)---- set和map

C语法&#xff08;17&#xff09;---- 二叉搜索树_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130174864 目录 1.set的介绍 1.set使用 1.基本结构 2.insert 3.erase 4.find 5.count 2.multiset 1.count 2.find 2.map的介绍 1.map …

zookeeper + kafka集群搭建详解

目录 1.消息队列介绍 1.为什么需要消息队列 &#xff08;MO&#xff09; 2.使用消息队列的好处 3.消息队列的两种模式 2.Kafka相关介绍 1.Kafka定义 2.Kafka简介 3. Kafka的特性 3.Kafka系统架构 1. Broker&#xff08;服务器&#xff09; 2. Topic&#xff08;一个队…

GaussDB数据库存储过程介绍

文章目录一、前言二、GaussDB中的定义三、存储过程的使用场景四、存储过程的使用优缺点五、存储过程的示例及示例解析1、GaussDB存储过程语法格式2、GaussDB存储过程语法示例3、存储过程的调用方法七、总结一、前言 华为云数据库GaussDB是一款高性能、高安全性的云原生数据库&…