日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

每天一道LeetCode-----有序数组右移n位后查找某个元素

發布時間:2024/4/19 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 每天一道LeetCode-----有序数组右移n位后查找某个元素 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Search in Rotated Sorted Array

原題鏈接Search in Rotated Sorted Array

一個無重復項的遞增序列右移了一定距離,在右移后的序列中查找是否有某個元素
比如[0,1,2,4,5,6,7]右移4位變為[4,5,6,7,0,1,2],在[4,5,6,7,0,1,2]中查找某個元素,事先不知道移動了多少位


對于有序序列,首先可以想到的是利用二分法查找,但是序列別移動后的起點不再是最左邊的位置。比如說上面的例子,起點0在下標為4的位置,所以不一定滿足nums[0] < nums[n - 1],不能直接使用二分法。
但是因為是整體移動,局部仍然是有序的,所以如果確定了某個區間是有序的,那么還是可以使用二分法的

下面的*代表起點

o * o o o o o 大 小 中 left middle right 如果起點在middle的左側,那么nums[left],nums[middle],nums[right]的大小關系如上 可通過nums[middle] < nums[right]判斷起點在middle左邊o o o o o * o 中 大 小 left middle right 如果起點在middle的右側,那么nums[left],nums[middle],nums[right]的大小關系如上 可通過nums[middle] > nums[right]判斷起點在middle右邊

以第一種情況為例(起點在middle左側)即nums[middle] < nums[right]
如果目標元素在[middle, right]區間,那么一定有nums[target] >= nums[middle] && nums[target] <= nums[right]
否則,目標元素在[left, middle]區間內
因為[middle, right]一定是遞增的,所以可以判斷目標元素是否在這個區間內,而[left, middle]區間不是遞增的,故不能判斷。

第二種情況同理
代碼如下

class Solution { public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while(left < right){int middle = (left + right) / 2;if(nums[middle] == target)return middle;/* 第一種情況,起點在middle左邊 */if(nums[middle] < nums[right]){/* 目標在[middle, right]區間,因為nums[middle]已經比較過了,所以middle不需要等號 */if(target > nums[middle] && target <= nums[right])left = middle + 1;elseright = middle - 1;}/* 第二種情況,起點在middle右邊 */else{/* 目標在[left, middle]區間,middle不需要等號,原因同上 */if(target < nums[middle] && target >= nums[left])right = middle - 1;elseleft = middle + 1;}}return left < nums.size() && nums[left] == target ? left : -1;}};

擴展
原題鏈接Search in Rotated Sorted Array II

要求和上面的一樣,只是所給序列可能帶有重復項。
此時情況就不僅僅是上面兩種,比如

o o o o o * o 小 小 大 小 left middle right 如果起點在middle的右側,那么有可能nums[middle] == nums[right]

以[3,1,1]中找3為例
此時nums[middle] == nums[right],那么通過上面的方法判斷得知起點在右邊(進入else),但是此時[left, middle]不是遞增的。而上面的方法必須保證

  • 如果起點在右邊,那么[left, middle]是遞增的
  • 如果起點在左邊,那么[middle, right]是遞增的

解決辦法是通過比較nuns[middle] < nums[right]判斷起點在左邊,比較nums[middle] > nums[right]判斷起點在右邊,否則有重復項,將right左移,重新判斷。

為什么左移right
因為nums[middle] == nums[right],可知存在重復項,那么無法保證[left, middle]是遞增的,所以縮小范圍,將區間變為[left, right-1],嘗試去掉重復項。

代碼如下

class Solution { public:bool search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while(left < right){int middle = (left + right) / 2;if(nums[middle] == target)return true;/* 起點在左邊 */if(nums[middle] < nums[right]){if(target > nums[middle] && target <= nums[right])left = middle + 1;elseright = middle - 1;}/* 起點在右邊 */else if(nums[middle] > nums[right]){if(target < nums[middle] && target >= nums[left])right = middle - 1;elseleft = middle + 1;}/* 有重復項 */else{--right;}}return left < nums.size() && nums[left] == target ? true : false;} };

總結

以上是生活随笔為你收集整理的每天一道LeetCode-----有序数组右移n位后查找某个元素的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。