在循環遞增一次的數組中插入元素

文章目錄

  • 題目
  • 思路
    • 如何建立左右區間?
    • 如何查找最高點?
    • 那我們怎么判斷 `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)

算法思想是:

  1. 先以數組首元素、尾元素作為二分查找的左右邊界,中間元素暫定為high
  2. 左邊界小于右邊界 作為while的循環條件
  3. 首先判斷此時的high是否大于首元素
  4. 大于首元素證明此時的high處于 真正最高點的左邊就是真正最高點,此時需要判定high+1中元素和high中元素之間的關系:
  1. 如果high+1中元素大于high中元素,表明 真正最高點應該在high的左邊,因此更新左邊界—— left = high + 1
  2. 如果high+1中元素小于high中元素,表明 high即為真正最高點 ,因此break出while循環即可
  1. 小于首元素證明此時的high處于 真正最高點的右邊 ,此時需要判定high和high-1所指元素之間的關系:
  1. 如果 res[high - 1] < res[high] (如舉例中high=6時,4>3),表明最高點仍在 high-1的左邊,也就是high-1也處于真正最高點的右邊,因此要更新右邊界—— right = high - 2
  2. 如果 res[high - 1] > res[high] , 此時表明high-1即為最高點,因此將high–并break出while循環即可
  1. 每次循環更新完左右邊界之后需要更新high值—— high = left + (right - left) / 2;
  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 到底處于什么樣的位置呢?

這時應該結合之前我們說到的一句話:

首元素一定 大于等于 尾元素

那我們做個歸納,如果:

  1. num > res[0] ,num 處于 high 左邊
  2. res[end] < num == res[0] ,num 處于 high 右邊,插入到尾元素的位置
  3. res[end] == num == res[0] ,不可能出現這種情況,因為這種情況下num沒有位置可以插入。
  4. res[end] == num < res[0] ,num 處于 high 左邊,插入到首元素的位置
  5. 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;
} 

如何確定插入位置?

建立好左右邊界后就可以根據二分查找來確定插入位置了。

  1. 當左邊界小于右邊界時執行二分查找。
  2. 中間點(mid)對應的元素小于 num 時,左邊界更改為 mid+1
  3. 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;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443795.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443795.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443795.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Unable to find 'struts.multipart.saveDir' property setting.

Unable to find struts.multipart.saveDir property setting. 今天在做工作的時候遇到了這個問題&#xff0c;后來經過百度&#xff0c;終于知道了原因&#xff0c;現在記錄下來&#xff0c;以備以后查看。 1.struts.multipart.saveDir沒有配置 2.struts.multipart.saveDir用…

表示數值的字符串(有限狀態自動機與搜索)

文章目錄題目思路一代碼一思路二代碼二題目 思路一 考察有限狀態自動機&#xff08;參考jyd&#xff09;&#xff1a; 字符類型&#xff1a; 空格 「 」、數字「 0—9 」 、正負號 「 」 、小數點 「 . 」 、冪符號 「 eE 」 。 狀態定義&#xff1a; 按照字符串從左到右的…

樹的子結構

文章目錄題目深搜深搜代碼廣搜廣搜代碼題目 輸入兩棵二叉樹A和B&#xff0c;判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構) B是A的子結構&#xff0c; 即 A中有出現和B相同的結構和節點值。 例如: 給定的樹 A: 給定的樹 B&#xff1a; 返回 true&#xff0c;因為…

寫題過程中碰見的小問題

文章目錄和--vector二維vector的初始化數組中最大的數max_element()數組所有元素之和accumulate()vector數組去重對pair類型的vector排序對元素都為正整數的vector利用sort默認的升序排列進行降序排列一維數組轉二維數組size_t和int如何不用臨時變量交換兩個數?將類函數的形參…

LeetCode——二叉樹序列化與反序列化

文章目錄題目思路問題一問題二代碼實現題目 請實現兩個函數&#xff0c;分別用來序列化和反序列化二叉樹。 設計一個算法來實現二叉樹的序列化與反序列化。不限定序列 / 反序列化算法執行邏輯&#xff0c;你只需要保證一個二叉樹可以被序列化為一個字符串并且將這個字符串反序…

jsp中生成的驗證碼和存在session里面的驗證碼不一致的處理

今天在調試項目的時候發現&#xff0c;在提交表單的時候的驗證碼有問題&#xff0c;問題是這樣的&#xff1a;就是通過debug模式查看得知&#xff1a;jsp頁面生成的驗證碼和表單輸入的頁面輸入的一樣&#xff0c;但是到后臺執行的時候&#xff0c;你會發現他們是不一樣的&#…

求1~n這n個整數十進制表示中1出現的次數

文章目錄題目思路代碼復雜度分析題目 輸入一個整數 n &#xff0c;求1&#xff5e;n這n個整數的十進制表示中1出現的次數。 例如&#xff0c;輸入12&#xff0c;那么1&#xff5e;12這些整數中包含1 的數字有1、10、11和12。可得1一共出現了5次。 思路 將個位、十位……每位…

求數字序列中的第n位對應的數字

文章目錄題目思路代碼復雜度分析致謝題目 數字以0123456789101112131415…的格式序列化到一個字符序列中。在這個序列中&#xff0c;第5位&#xff08;從下標0開始計數&#xff09;是5&#xff0c;第13位是1&#xff0c;第19位是4&#xff0c;等等。 請寫一個函數&#xff0c…

一學就廢的歸并排序

文章目錄其他與排序有關的文章原理代碼實現復雜度分析其他與排序有關的文章 一學就廢的三種簡單排序【冒泡、插入、選擇】 原理 歸并排序&#xff08;Merge sort&#xff09;&#xff1a; 歸并排序對元素 遞歸地 進行 逐層折半分組&#xff0c;然后從最小分組開始&#xff0c…

神奇的x -x,Lowbit函數的實現方式!

文章目錄-xx & -x&#xff0c;當x為偶數時x & -x&#xff0c;當x為奇數時x&-x 的實際用途-x -x 在二進制里表示對 x 的二進制按位取反(~x)之后再加 1 &#xff0c;即 -x ~x1x & -x&#xff0c;當x為偶數時 在執行 x & -x 時&#xff0c;若 x 為偶數&am…

JAVA實現把指定文件夾下的所有文件壓縮成zip包

1.代碼如下&#xff1a; package cn.gov.csrc.base.util;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import…

樹狀數組的相關知識 及 求逆序對的運用

文章目錄樹狀數組概念前綴和和區間和樹狀數組原理區間和——單點更新前綴和——區間查詢完整代碼離散化sort函數unique函數去重erase函數僅保留不重復元素通過樹狀數組求逆序對樹狀數組概念 樹狀數組又名二叉索引樹&#xff0c;其查詢與插入的復雜度都為 O(logN)&#xff0c;其…

二叉搜索樹相關知識及應用操作

文章目錄概念查找二叉搜索樹的第k大節點概念 二叉查找樹&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff08;又名&#xff1a;二叉搜索樹&#xff0c;二叉排序樹&#xff09;——它或者是一棵空樹&#xff0c;或者是具有下列性質的二叉樹&#xff1a; 若它的…

二叉樹相關知識及求深度的代碼實現

文章目錄樹二叉樹滿二叉樹和完全二叉樹二叉樹的性質代碼實現求二叉樹的深度樹 樹是一種非線性的數據結構&#xff0c;它是由n個有限結點組成一個具有層次關系的集合。 樹的相關名詞&#xff1a; 根節點&#xff1a;沒有前驅結點的結點。父節點&#xff0c;子節點&#xff1a…

平衡樹相關知識及如何判斷一棵樹是否平衡

文章目錄概念代碼實現判斷一棵二叉樹是否為平衡樹概念 平衡樹(Balance Tree&#xff0c;BT) 指的是&#xff0c;任意節點的子樹的高度差都小于等于1。 常見的符合平衡樹的有&#xff1a; B樹&#xff08;多路平衡搜索樹&#xff09;AVL樹&#xff08;二叉平衡搜索樹&#xf…

大端小端存儲模式詳解及判斷方法

文章目錄大小端模式的概念兩種模式出現原因兩種模式的優劣大小端的應用情景判斷機器的字節序大小端模式的概念 當我們查看數據在內存中的存儲情況時&#xff0c;我們經常會發現一個很奇怪的現象&#xff0c;什么現象呢&#xff1f; int main() {int i 12;return 0; }數據在內…

Linux 內存管理 | 物理內存、內存碎片、伙伴系統、SLAB分配器

文章目錄物理內存物理內存分配外部碎片內部碎片伙伴系統(buddy system)slab分配器物理內存 在Linux中&#xff0c;內核將物理內存劃分為三個區域。 在解釋DMA內存區域之前解釋一下什么是DMA&#xff1a; DMA&#xff08;直接存儲器訪問&#xff09; 使用物理地址訪問內存&am…

Linux 內存管理 | 虛擬內存管理:虛擬內存空間、虛擬內存分配

文章目錄虛擬地址空間用戶空間內核空間用戶空間內存分配malloc內核空間內存分配kmallocvmalloc虛擬地址空間 在早期的計算機中&#xff0c;程序是直接運行在物理內存上的&#xff0c;而直接使用物理內存&#xff0c;通常都會面臨以下幾種問題&#xff1a; 內存缺乏訪問控制&a…

Linux | 編譯原理、gcc的命令參數、自動化構建工具 make/Makefile

文章目錄編譯原理預處理編譯匯編鏈接gcc的常用命令參數make 和 Makefile 的概念make的運行通配符自動化變量偽目標.PHONE:【命令】編譯原理 在解釋 makefile 前&#xff0c;首先解釋一下 .c 文件變成 .exe 文件要經過的四個步驟——預處理、編譯、匯編和鏈接&#xff08;參考來…

全排列變種:限定 排列的差值范圍 及 排列中的元素個數

文章目錄題目描述思路代碼實現題目描述 詳細描述&#xff1a;字節跳動2019春招研發部分編程題——萬萬沒想到之抓捕孔連順 輸入描述&#xff1a; 第一行包含空格分隔的兩個數字 N和D(1?≤?N?≤?1000000; 1?≤?D?≤?1000000) 第二行包含N個整數&#xff08;取值區間為…