在循环递增一次的数组中插入元素
文章目录
- 题目
- 思路
- 如何建立左右区间?
- 如何查找最高点?
- 那我们怎么判断 `num` 到底处于什么样的位置呢?
- 如何确定插入位置?
- 插入元素
- 代码
题目
给一个只循环递增一次的数组 res,res 满足首元素大于等于尾元素,形如:
4,5,6,7,2,4
再给出一个整型数字 num,将其插入到数组中应在的位置。
示例:
输入:
res = 4,5,6,7,2,4
num = 3
输出:
4,5,6,7,2,3,4
思路
用二分查找确定应该插入的位置,难点在于左右区间的建立。
如何建立左右区间?
首先明确两点,对于整个数组而言:
- 首元素一定
大于等于
尾元素 - 以数组的最大值为界限,最大值左边的元素一定
大于等于
右边的元素
用图像表示数组是这样的(黑色表下标,紫色表值):
我们可以看到,要插入的元素无非在最高点的左边或右边(自下文始,最高点用high替代,首元素位置用begin表示,尾元素位置用last表示):
- 当
num
处于最高点左边时,二分查找的范围应该是[begin, high]
- 当
num
处于最高点右边时,二分查找的范围应该是[high+1,last]
也就是说,划定二分查找范围(左右区间的建立)的重中之重在于最高点的确定。
如何查找最高点?
个人想到两种方法:
- 遍历查找,时间复杂度O(n)
算法思想没有什么多说的,中规中矩的遍历。
int high = 0;
for (int i = 1; i < res.size(); i++) {if (res[high] > res[i]) {break;}high = i;
}
- 二分查找,时间复杂度O(log2n)
算法思想是:
- 先以数组首元素、尾元素作为二分查找的左右边界,中间元素暂定为high
- 以
左边界小于右边界
作为while的循环条件 - 首先判断此时的high是否大于首元素
- 大于首元素证明此时的high处于
真正最高点的左边
或就是真正最高点
,此时需要判定high+1中元素和high中元素之间的关系:
- 如果high+1中元素大于high中元素,表明
真正最高点应该在high的左边
,因此更新左边界——left = high + 1
- 如果high+1中元素小于high中元素,表明
high即为真正最高点
,因此break出while循环即可
- 小于首元素证明此时的high处于
真正最高点的右边
,此时需要判定high和high-1所指元素之间的关系:
- 如果
res[high - 1] < res[high]
(如举例中high=6时,4>3),表明最高点仍在 high-1的左边,也就是high-1也处于真正最高点的右边,因此要更新右边界——right = high - 2
- 如果
res[high - 1] > res[high]
, 此时表明high-1即为最高点,因此将high–并break出while循环即可
- 每次循环更新完左右边界之后需要更新high值——
high = left + (right - left) / 2;
- 跳出while循环得到的high即为最高点的位置
int size = res.size() - 1;
int left = 0;
int right = size;
int high = left + (right - left) / 2;
int flag = res[0];
while (left < right) {if (res[high] >= flag) {if (res[high + 1] > res[high]) {left = high + 1;}else {break;}}else {if (res[high - 1] < res[high]) {right = high - 2;}else {high--;break;}}high = left + (right - left) / 2;
}
那我们怎么判断 num
到底处于什么样的位置呢?
这时应该结合之前我们说到的一句话:
首元素一定 大于等于
尾元素
那我们做个归纳,如果:
num > res[0]
,num 处于 high 左边res[end] < num == res[0]
,num 处于 high 右边,插入到尾元素的位置res[end] == num == res[0]
,不可能出现这种情况,因为这种情况下num没有位置可以插入。res[end] == num < res[0]
,num 处于 high 左边,插入到首元素的位置res[end] > num
,num 处于 high 右边
第二点和第四点是什么意思呢?
关于第二点,我们举这样一个例子:
输入:
res = 5,6,7,2,4
num = 5
输出:
res = 5,6,7,2,4,5
关于第四点,我们举这样一个例子:
输入:
res = 6,7,2,4,5
num = 5
输出:
res = 5,6,7,2,4,5
因此根据上面的归纳我们可以得到代码:
注意:因为第三种情况不可能出现,因此我们在描述第2、4种情况时可以省略大小比较,因为当2、4种描述的等于关系成立时,大小关系必然成立。
if (res[size] > num || num == res[0]) { // num处于high右边left = high + 1;right = size;
}
if(num > res[0] || num == res[size]) { // num处于high左边left = 0;right = high;
}
如何确定插入位置?
建立好左右边界后就可以根据二分查找来确定插入位置了。
- 当左边界小于右边界时执行二分查找。
- 中间点(mid)对应的元素小于
num
时,左边界更改为mid+1
。 mid
对应的元素大于num
时,右边界更改为mid-1
。
int mid = left + (right - left) / 2;
while (left <= right)
{if (res[mid] < num) {left = mid + 1; }else {right = mid - 1;}mid = left + (right - left) / 2;
}
插入元素
最终使用insert函数进行插入:
res.insert(res.begin() + mid, num);
insert会将给定值插入到给定位置之前。
代码
class Solution {public:vector<int> fun(vector<int> res, int num) {int size = res.size() - 1;int left = 0;int right = size;/*int high = 0;for (int i = 1; i < res.size(); i++) {if (res[high] > res[i]) {break;}high = i;}*/// 与上面注释部分一样都是查最高点int high = left + (right - left) / 2;int flag = res[0];while (left < right) {if (res[high] > flag) {if (res[high + 1] > res[high]) {left = high + 1;}else {break;}}else {if (res[high - 1] < res[high]) {right = high - 2;}else {high--;break;}}high = left + (right - left) / 2;}// 确定左右边界if (res[size] > num || num == res[0]) { // num处于high右边left = high + 1;right = size;}if(num > res[0] || num == res[size]) { // num处于high左边left = 0;right = high;} // 确定插入位置int mid = left + (right - left) / 2;while (left <= right){if (res[mid] < num) {left = mid + 1; }else {right = mid - 1;}mid = left + (right - left) / 2;} res.insert(res.begin() + mid, num);return res;}
};
用例测试:
int main() {Solution s;vector<int> iv = { 4,5,6,7,1,2,4 };int num = 3;iv = s.fun(iv, num);for (auto i = iv.begin(); i != iv.end(); i++) {cout << *i << " ";}cout << endl;
}
在循环递增一次的数组中插入元素相关推荐
- java向数组中插入元素
/*** * @Title: test_insert_array* @Description: 该方法的主要作用:像数组中插入元素* @param 设定文件 * @return 返回类型:void * ...
- 向一个数组中插入元素
向一个数组中插入元素是平时很常见的一件事情.你可以使用push在数组尾部插入元素,可以用unshift在数组头部插入元素,也可以用splice在数组中间插入元素. 但是这些已知的方法,并不意味着没有更 ...
- 有序数组中插入元素依然保持有序
有序数组中插入元素依然保持有序 如何在一个有序数组中插入元素,使得数组依然保持有序,废话不多说直接上代码(C/C++) 如何在一个有序数组中插入元素,使得数组依然保持有序,废话不多说直接上代码(C/C ...
- Java数组中插入元素
**问题:Java中如何向一个已经升序排序好的数组中插入元素,得到的数组依然是升序数组 效果: int[] array = {1,3,7,12,24,36,48}; 插入数字9后新数组为 int[] ...
- java 数组中插入元素_Java数组添加元素
java 数组中插入元素 How to add elements to an array in java We know that java array size is fixed, so we ca ...
- Swift for循环:用于索引,数组中的元素?
本文翻译自:Swift for loop: for index, element in array? Is there a function that I can use to iterate ove ...
- C++数组中插入元素。
问题: 在已经排序的数组中插入一个数,插入后的数组仍是有序的. 为了简化问题,将顺序规定为升序数组类型为double. 插入函数的代码如下: //将data插入到数组arr中,使插入后仍是升序. vo ...
- vb excel 连续多个值赋值_VB实现向数组中插入元素
爱学习,更爱VB编程 大家好,数组在编程中应用广泛.在各种编程语言中,数组都占据非常重要的地位,所以熟练应用数组去解决程序中的问题就显得尤为必要了. 今天,我们共同来学习如何把一个元素插入到数组中. ...
- C语言,往排好序的数组中插入元素
例题:有一个已经排好序的数组,元素分别是:1,3,5,7,9,从键盘上输入一个元素,将这个元素插入到数组中,使数组仍保持从小到大排序. 输出时各元素的最小宽度为5. 例: (1)输入:0 输出: ...
最新文章
- JavaScript 学习笔记— —类型判断
- laravel+vue.js的学习以及为什么浏览器中要有井号“#”
- 前后端传递时间参数偶遇参数类型转换异常
- 登录多实例MySQL失败,修改密码临时解决,原因不明
- 扩展控件--NumberTextBox
- JavaScript基础学习(二)—JavaScript基本概念
- 最近一段时间遇到的费了时间的问题
- 分支程序设计02 - 零基础入门学习C语言11
- 深入浅出 python epub_《机器学习从认知到实践(第2辑)(套装共3册,Python+TensorFlow)》epub+mobi+azw3...
- 2017IEC计算机第二次作业
- 斯坦福首位华人女院长,“人造皮肤”赋予机器和残疾人触觉
- 阿里云高级专家王林平:云数据库的运维体系构建
- 基于3D技术的机器视觉解决方案
- Mac配置OpenGL环境
- 远程桌面系统管理员以限制你登入计算机,windows远程连接时:系统管理员已经限制你可以使用的登录类型(网络或交互式)解决办法...
- exlsx表格教程_excel表格格式刷的使用教程详解
- windows下远程连接Mysql
- 从苹果创业神话看资本运营应集中优势兵力
- [leetcode]剑指offer(C++版题解)
- ECCV 2022开奖!清华、浙大校友斩获最佳论文奖
热门文章
- python正则表达式group用法_【Python】正则表达式用法
- vue v-if判断数组元素的值_Vue项目上线做的一些基本优化
- access vba代码大全_VBA 实践指南 -- VBA连接各种数据库
- c语言学籍管理系统小程序,学籍业务办理系统(开源 v2.0发布 优化代码,增加小程序端)...
- c语言链表复数实验,数据结构实验—复数计算器 大神提意见
- datagridview 当前上下文中不存在bind_全面解析JavaScript中this指向问题
- DMA及cache一致性的学习心得
- linux+qt+定时精度,Qt QTimer测试定时精度
- C#的变迁史10 - C# 5.0 之其他增强篇
- 第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions