目次
35.挿入位置の探索
質問の意味:
ソートされた配列とターゲット値を指定すると、配列内でターゲット値を検索し、そのインデックスを返します。ターゲット値が配列内に存在しない場合は、その値が順番に挿入される位置を返します。
時間計算量が のアルゴリズムを使用する必要があります
O(log n)
。
【入力例】 nums = [1,3,5,6]、target = 5
【出力サンプル】2
問題解決のアイデア: 最も単純な二分探索では、ソートされた配列を指定して、配列の添字に従って範囲の中点を直接見つけ、ターゲットと比較します。ターゲットより大きい場合は、検索範囲を左に狭めます。間隔; ターゲットが笑った場合、検索範囲を適切な間隔に絞り込み、それらが等しい場合は直接戻ります。
class Solution {
public int searchInsert(int[] nums, int target) {
int l =0;
int r = nums.length-1;
while(l<=r){
int mid = (l+r)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid]<target){
l=mid+1;
}else if(nums[mid]>target){
r=mid-1;
}
}
return l;
}
}
時間: 100.00% を達成
メモリ: 82.77% 上回る
74. 二次元行列の検索
質問の意味:
次の 2 つのプロパティを満たす整数行列が与えられます
m x n
。
- 各行の整数は、左から右へ非減少順に配置されます。
- 各行の最初の整数は、前の行の最後の整数より大きくなります。
整数を返します
target
。それがtarget
行列内にある場合はそれを返しtrue
、それ以外の場合はそれを返しますfalse
。
[入力例] 行列 = [[1,3,5,7],[10,11,16,20],[23,30,34,60]]、ターゲット = 3
[出力サンプル] true
問題解決のアイデア: 原理は前の質問と同じですが、ここでは 2 次元の行列になります。質問の要件に応じて、2 次元行列を 1 次元配列とみなすことができ、前の質問の方法をそのまま使用できます。
行列には m 行、n 列があります。1 次元行列では、中央のインデックスは Mid で、2 次元行列での対応する座標は次のとおりです。
i = mid / n;//1 行に数字は何個ありますか?また、全体の行は何個存在できますか?
j = mid % n; //現在の行には何列残っていますか?
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;
int low = 0, high = m * n - 1;
while(low <= high){
//这里有个坑,就是二维数组跟一维数组还不太一样,这里直接除之后还需要加上low
//加上low的特殊原因是保证mid可以代表其在一维数组中的真实坐标
int mid = (high - low) / 2 + low;
int x = matrix[mid/n][mid % n];
if(x < target){
low = mid + 1;
}else if(x > target){
high = mid - 1;
}else{
return true;
}
}
return false;
}
}
時間: 100.00% を達成
メモリ: 95.25% を達成
162. ピークを見つける
質問の意味:
ピーク要素とは、その値が左右に隣接する値よりも厳密に大きい要素です。
整数の配列を指定して
nums
、ピーク要素を見つけてそのインデックスを返します。配列には複数のピークが含まれる場合がありますが、その場合は 任意のピークの位置を返すだけです 。と仮定することができます
nums[-1] = nums[n] = -∞
。
O(log n)
この問題を解決するには、時間計算量を考慮したアルゴリズムを実装する必要があります 。
【入力例】 nums =
[1,2,3,1]
【出力サンプル】2
問題解決のアイデア: 最大値を見つけます。
class Solution {
public int findPeakElement(int[] nums) {
int n = nums.length;
int max = 0;
for(int i=1;i<nums.length;++i){
if(nums[i] > nums[max]){
max = i;
}
}
return max;
}
}
時間: 100.00% を達成
メモリ: 95.66% を達成
33. 回転ソート配列の検索
質問の意味:
整数の配列は
nums
昇順に並べ替えられ、配列内の値は 互いに区別されます 。関数に渡される前に、
nums
未知のインデックスk
( ) に対して回転0 <= k < nums.length
が実行され 、配列は (インデックスは 0 からカウントを開始します ) になります。たとえば、 下付き文字で 回転すると 、 になる場合があります 。[nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
[0,1,2,4,5,6,7]
3
[4,5,6,7,0,1,2]
回転された 配列
nums
と整数 を指定しますtarget
。nums
ターゲット値がその中に存在する 場合はtarget
その添え字を返し、それ以外の場合は を返します-1
。この問題を解決するには、時間計算量を考慮したアルゴリズムを設計する必要があります
O(log n)
。
【入力例】 nums = [
4,5,6,7,0,1,2]
, target = 0【出力サンプル】4
問題解決のアイデア: まず、二分探索を使用して Mid を見つけます。left<mid の場合、[left, Mid] 範囲が適切であることが証明されます。または、従来の二分探索を使用してそれを見つけます。それ以外の場合は、[left, Mid] です。無秩序になり、再び分裂する。
[mid,right] についても同様で、mid<right の場合は検索を続け、そうでない場合は分割を続けます。
class Solution {
public int search(int[] nums, int target) {
int low = 0,high = nums.length - 1;
while(low <= high){
int mid = (low + high) /2;
if(nums[mid] == target) return mid;
if(nums[low] <= nums[mid]){
if (target >= nums[low] && target < nums[mid]){
high = mid - 1;
}else{
low = mid + 1;
}
}else{
if (target > nums[mid] && target <= nums[high]){
low = mid + 1;
} else{
high = mid - 1;
}
}
}
return -1;
}
}
時間: 100.00% を達成
メモリ: 80.30% で負けました