在循环递增一次的数组中插入元素
文章目录
- 题目
- 思路
- 如何建立左右区间?
- 如何查找最高点?
- 那我们怎么判断 `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 输出: ...
最新文章
- 在C#中SendMessage和PostMessage的参数传递
- MyAdapter Andriod
- pytoch word_language_model 代码阅读
- 我们凭什么相信 5G 很安全?
- resnet网络结构_深度学习之16——残差网络(ResNet)
- 串口光猫设备结构及主要特点介绍
- 【心随笔】叙述你成功完成一件事情的方法
- matlab视频旋转振动,基于MATLAB的振动合成及左旋与右旋的动态模拟演示
- 能安装python库的app_APP自动化之安装Python(类库)环境
- 软件工程个人作业12
- 《Java安全编码标准》一2.9 IDS08-J净化传递给正则表达式的非受信数据
- 计算机用户系统软件,计算机软件系统
- python各个版本区别_Python 的各个版本
- Xcode Undefined symbols 错误
- [转载]关于字体的一些常识
- 译《Office商业应用程序入门》
- 量子通信——量子的概念与量子力学
- python统计水仙花数个数_Python一句代码实现找出所有水仙花数的方法
- perp系列之一:关于perp
- Yoyo OS安装过程
热门文章
- asp.net web开发步骤_WEB开发流程
- 数据产品经理修炼手册pdf_【尼读书】数据产品经理修炼手册(附思维导图)
- bbb sdk6 ll_rw_block分析
- Windows CE创建桌面快捷方式
- 二叉树的深度_十七:二叉树的最小深度
- python3发布时间_Python3优雅操作-时间处理与定时任务
- 【转】GigE Vision简介
- 【转】TFS自动签出解决方案sln或者项目文件csproj的解决办法
- TFS版本管理(八)
- 深入探究JVM | klass-oop对象模型研究