Leetcode经典题5--轮转数组

题目描述

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

输入输出示例 :

输入: nums = [1,2,3,4,5,6,7], k = 3

输出: [5,6,7,1,2,3,4]

解释:

向右轮转 1 步: [7,1,2,3,4,5,6]

向右轮转 2 步: [6,7,1,2,3,4,5]

向右轮转 3 步: [5,6,7,1,2,3,4]

解题方案

模除操作

方式一:使用额外的数组

算法思想

使用额外的数组来将每个元素放至正确的位置。用 n 表示数组的长度,我们遍历原数组,将原数组下标为 i 的元素放至新数组下标为 (i+k) mod n 的位置,最后将新数组拷贝至原数组即可

实现代码

class Solution {
    public void rotate(int[] nums, int k) {
        //获取数组长度
        int n = nums.length;
        //创建一个新数组
        int[] newArr = new int[n];
        //遍历原数组,将数组放到正确的位置
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i];
        }
        System.arraycopy(newArr, 0, nums, 0, n);
    }
}

复杂度分析

  • 时间复杂度: O(n),其中 n 为数组的长度。
  • 空间复杂度: O(n)。
方法二:环状替换

算法思想:

为了防止元素覆盖的问题,因此,从另一个角度,我们可以将被替换的元素保存在变量 temp 中,从而避免了额外数组的开销。

我们用下面的例子更具体地说明这个过程:

nums = [1, 2, 3, 4, 5, 6]

k = 2

 

  • 我们从位置 0 开始,最初令 temp=nums[0]。
  • 根据规则,位置 0 的元素会放至 (0+k) mod n 的位置,令 x=(0+k) mod n,此时交换 temp 和 nums[x],完成位置 x 的更新。
  • 然后,我们考察位置 x,并交换 temp 和 nums [(x+k) mod n],从而完成下一个位置的更新。不断进行上述过程,直至回到初始位置 0。每次都考察要更新的位置

容易发现,当回到初始位置 0 时,有些数字可能还没有遍历到,此时我们应该从下一个数字开始重复的过程

怎么才算遍历结束呢?

我们不妨先考虑这样一个问题:从 0 开始不断遍历,最终回到起点 0 的过程中,我们遍历了多少个元素?

由于最终回到了起点,故该过程恰好走了整数数量的圈,不妨设为 a 圈;

再设该过程总共遍历了 b 个元素。

我们用总元素数b 除以 每圈遍历的元素个数n/k 会得到总共遍历的圈数a

因此,我们有 an=bk,即 an 一定为 n,k 的公倍数。又因为我们在第一次回到起点时就结束,因此 a 要尽可能小,故 an 就是 n,k 的最小公倍数 lcm(n,k),因此 b 就为 lcm(n,k)/k。

这说明单次遍历会访问到 lcm(n,k)/k 个元素。为了访问到所有的元素,我们需要进行遍历的次数为

其中 gcd 指的是最大公约数。

实现代码

使用单独的变量 count 跟踪当前已经访问的元素数量,当 count=n 时,结束遍历过程。

class Solution {
    public void rotate(int[] nums, int k) {
        //数组长度
        int n = nums.length;
        
        k = k % n;
        //遍历次数 k和n的最大公约数
        int count = gcd(k, n);
        //循环遍历
        for (int start = 0; start < count; ++start) {
            //当前遍历的数组下标
            int current = start;
            //开始时的数组元素
            int prev = nums[start];
            do {
                //将要更新的数组下标
                int next = (current + k) % n;
                //将被覆盖的数组值赋给temp
                int temp = nums[next];
                //更新
                nums[next] = prev;
                prev = temp;
                current = next;
            } while (start != current);
        }
    }

    public int gcd(int x, int y) {
        return y > 0 ? gcd(y, x % y) : x;
    }
}

复杂度分析

时间复杂度:O(n),其中 n 为数组的长度。每个元素只会被遍历一次。

空间复杂度:O(1)。我们只需常数空间存放若干变量。

方法三:数组翻转

算法思想

该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 k mod n 个元素会移动至数组头部,其余元素向后移动 k mod n 个位置。

实现步骤

  • 我们可以先将所有元素翻转,这样尾部的 k mod n 个元素就被移至数组头部,
  • 然后我们再翻转 [0,kmodn−1] 区间的元素和 [kmodn,n−1] 区间的元素即能得到最后的答案。

我们以 n=7,k=3 为例进行如下展示:

实现代码

class Solution {
    public void rotate(int[] nums, int k) {
        //确定分开反转的位置
        k %= nums.length;
        //反转整个数组
        reverse(nums, 0, nums.length - 1);
        //反转前一半
        reverse(nums, 0, k - 1);
        //反转后一半
        reverse(nums, k, nums.length - 1);
    }
    //数组翻转
    public void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start += 1;
            end -= 1;
        }
    }
}

复杂度分析

时间复杂度:O(n),其中 n 为数组的长度。每个元素被翻转两次,一共 n 个元素,因此总时间复杂度为 O(2n)=O(n)。

空间复杂度:O(1)。

欢迎大家点赞,评论加关注呦

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】每日一题 2024_12_9 判断国际象棋棋盘中一个格子的颜色(找规律)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;判断国际象棋棋盘中一个格子的颜色 最近力扣一直在出棋盘类的题目&#xff0c;这个月已经出了 9 天了&#xff0c;我倒要看看他是不是真能出一个月 代码与解题思路 先读题&#xff1a;题…

VRRP的知识点总结及实验

1、VRRP VRRP(Virtual Router Redundancy Protocol&#xff0c;虚拟路由器冗余协议)既能够实现网关的备份&#xff0c;又能解决多个网关之间互相冲突的问题&#xff0c;从而提高网络可靠性。 2、VRRP技术概述&#xff1a; 通过把几台路由设备联合组成一台虚拟的“路由设备”…

PostgreSQL 安装部署系列:使用YUM 方式在Centos 7.9 安装指定 PostgreSQL -15版本数据库

一、前言 千里之行始于足下&#xff0c;想学习一门数据库&#xff0c;首先要从安装部署开始&#xff0c;先拥有一套属于自己的学习测试库。为了更好的学习该数据库&#xff0c;可以选择一个在企业界使用率比较普及的操作系统&#xff0c;选择稳定版本的操作系统&#xff1b;如果…

Kafka Stream实战教程

Kafka Stream实战教程 1. Kafka Streams 基础入门 1.1 什么是 Kafka Streams Kafka Streams 是 Kafka 生态中用于 处理实时流数据 的一款轻量级流处理库。它利用 Kafka 作为数据来源和数据输出&#xff0c;可以让开发者轻松地对实时数据进行处理&#xff0c;比如计数、聚合、…

Flink:入门介绍

目录 一、Flink简介 2.1 Flink 架构 2.2 Flink 应用程序 运行模式 二、Flink 集群 部署 2.1 本地集群模式 2.1.1 安装JDK​编辑 2.1.2 下载、解压 Flink 2.1.3 启动集群 2.1.4 停止集群 2.2 Standalone 模式 2.2.0 集群规划 2.2.1 安装JDK 2.2.2 设置免密登录 2…

重生之我在异世界学编程之C语言:深入结构体篇(上)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文《1》 结构体的两种声明一、结构…

移动充电服务如何打破传统的新能源汽车充电难、找桩难问题?

中国新能源汽车在全球市场中占据重要地位&#xff0c;2024年上半年&#xff0c;中国新能源汽车销量达到494.4万辆&#xff0c;占全球新能源市场的68%。新能源汽车作为国家实现“碳中和”的重要途径之一&#xff0c;国家陆续出台各项产业政策&#xff0c;推动新能源汽车行业往标…

AI大模型ollama结合Open-webui

AI大模型Ollama结合Open-webui 作者:行癫(盗版必究) 一:认识 Ollama 1.什么是Ollama ​ Ollama是一个开源的 LLM(大型语言模型)服务工具,用于简化在本地运行大语言模型,降低使用大语言模型的门槛,使得大模型的开发者、研究人员和爱好者能够在本地环境快速实验、管理和…

Ubuntu Linux 图形界面工具管理磁盘分区和文件系统(八)

本文为Ubuntu Linux操作系统- 第八弹~~ 今天接着上文的内容&#xff0c;讲Linux磁盘分区存储的相关知识~ 上期回顾&#xff1a;命令行-管理磁盘分区和文件系统 今天看酷酷的雪獒铠甲&#xff01;&#xff01;雪獒铠甲合体~ 文章目录 磁盘管理器GNOME Disks主要功能安装命令 磁盘…

AI大模型的实践应用-探索智能科技的未来(附学习教程资源)

第一章&#xff1a;AI大模型技术概览 1.1 AI大模型的定义与特点 AI大模型&#xff0c;通常指的是参数数量达到数亿甚至数千亿的深度学习模型。这些模型因其庞大的参数量而得名&#xff0c;能够捕捉和学习数据中的复杂模式和关系。与传统模型相比&#xff0c;AI大模型具有更强的…

AI 数字人模型 Hallo2:让图片开口说话,一键修复模糊人脸

Hallo2 是由复旦大学 (Fudan University)、百度公司 (Baidu Inc) 和南京大学 (Nanjing University) 于 2024 年联合开发的一项先进技术&#xff0c;旨在生成长时间、高质量的唇形视频。该技术在原有的 Hallo 模型基础上进行了多项创新和改进&#xff0c;使其能够应对长时间视频…

反向代理-缓存篇

文章目录 强缓存一、Expires(http1.0 规范)二、cache-control(http1.1 出现的 header 信息)Cache-Control 的常用选项Cache-Control 常用选项的选择三、弊端协商缓存一、ETag二、If-None-Match三、Last-modified四、If-Modified-Since浏览器的三种刷新方式静态资源部署策略…

uniapp扭蛋机组件

做了一个uniapp的扭蛋机组件&#xff0c;可以前往下载地址下载 仅测试了vue2、3、h5页面微信小程序&#xff0c;理论支持全平台 使用方法简单&#xff0c;具有待机动效、抽奖中动效、掉落奖品动效&#xff0c;可以替换奖品图片&#xff0c;足以满足大部分抽奖页面需求。 示例图…

QT实战--QTreeWidget实现两种行颜色+QListWidget样式

本文主要介绍了QTreeWidget实现两种行颜色、点击打开父节点以及设置父子节点之间距离,同时附带介绍了QListWidget样式 树效果图: 列表效果图: 1.树样式的实现 1)使用代码: m_pLeftTreeWidget = new QTreeWidget(this);m_pLeftTreeWidget->setObjectName("suolue_t…

React - useActionState、useFormStatus与表单处理

参考文档&#xff1a;react18.3.1官方文档 一些概念&#xff1a; React 的 Canary 和 Experimental 频道是 React 团队用于发布和测试新功能的渠道。 useActionState useActionState 是一个可以根据某个表单动作的结果更新 state 的 Hook。 const [state, formAction, isPe…

Oracle之表空间迁移

问题背景&#xff1a;一个数据表随着时间的累积&#xff0c;导致所在表空间占用很高&#xff0c;里面历史数据可以清除&#xff0c;保留近2个月数据即可 首先通过delete删除了2个月以前的数据。 按网上的教程进行空间压缩&#xff0c;以下sql在表所在用户执行: -- 允许表重新…

如何在UI自动化测试中创建稳定的定位器?

如何在UI自动化测试中创建稳定的定位器&#xff1f; 前言1. 避免使用绝对路径2. 避免在定位器中使用索引3. 避免多个类名的定位器4. 避免动态和自动生成的ID5. 确保定位器唯一6. 处理隐藏元素的策略7. 谨慎使用基于文本的定位器8. 使用AI创建稳定的定位器 总结 前言 在自动化测…

从一条慢sql优化,深入探讨mysql的优化器优化机制

在某环境发现一个前端请求报错&#xff0c;经查为一条复杂的sql耗时约70s&#xff0c;最终导致前端响应超时。下面叙述下本次问题排查及根因分析过程&#xff0c;供其他同学参考。 本文中使用到的数据库是mariadb&#xff0c;对于mysql也是基本适用。 一&#xff0c;连接算法…

SpringBoot+OSS文件(图片))上传

SpringBoot整合OSS实现文件上传 以前,文件上传到本地(服务器,磁盘),文件多,大,会影响服务器性能 如何解决? 使用文件服务器单独存储这些文件,例如商业版–>七牛云存储,阿里云OSS,腾讯云cos等等 也可以自己搭建文件服务器(FastDFS,minio) 0 过程中需要实名认证 … 1 开…

Linux其三,yum源配置,定时任务,免密登录和查找命令

目录 一、Linux的两种软件安装方式 1、Yum源配置 2、linux中软件安装的另一种方式 rpm 3、安装mysql8.0 二、对虚拟机进行克隆 1、先关机 2、最新的状态&#xff0c;整个快照 3、开始克隆 4、修改克隆的服务器的硬件设置 5、修改克隆机的IP地址&#xff08;因为跟第一…