目次
二次元配列で検索_NiukeTiba_Niuke.com (nowcoder.com)
Peaks_NiukeTiba_Niuke.com (nowcoder.com) を探しています
array_Niuke Topic_Niuke.com (nowcoder.com) 内の逆順序ペア
回転配列の最小数_NiukeTiba_Niuke.com (nowcoder.com)
二次元配列で検索_NiukeTiba_Niuke.com (nowcoder.com)
質問の意味:
2 次元配列 (各 1 次元配列は同じ長さ) では、各行は左から右に昇順に並べ替えられ、各列は上から下に昇順に並べ替えられます。関数を完成させ、二次元配列と整数を入力し、配列に整数が含まれているかどうかを判定してください。
[
[1,2,8,9]、
[2,4,9,12]、
[4,7,10,13]、
[6,8,11,15]]
target = 7 の場合、true を返します。
target = 3 の場合、false を返します。
データ範囲:行列の長さと幅は0≤n,m≤5000を満たし、行列内の値は0≤val≤10^9を満たす
アドバンスト:空間計算量O(1)、時間計算量O(n+ m)
[入力例] 7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
[出力サンプル] true
問題解決のアイデア:
マトリックスのルールは、左から右、上から下に増加することです。
比較のために行列の右上隅にある a[row][col] を選択します。target<a[row][col] の場合、ターゲットが現在の列の左側にあることが証明され、それを見つけるには左行列。
target>a[row][col] の場合、ターゲットが現在の行の下にあることが証明され、以下の行列内を検索します。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param target int整型
* @param array int整型二维数组
* @return bool布尔型
*/
public boolean Find (int target, int[][] array) {
// write code here
int n = array.length;
int m = array[0].length;
int row = 0;//行
int col = m-1;//列
while(row < n && col >= 0){
if(target == array[row][col]){
return true;
}else if(target > array[row][col]){
row++;
}else{
col--;
}
}
return false;
}
}
Peaks_NiukeTiba_Niuke.com (nowcoder.com) を探しています
質問の意味:
長さ n の配列 nums を指定すると、ピーク値を見つけてそのインデックスを返します。配列には複数のピークが含まれる場合がありますが、その場合はいずれかのピークの位置を返すだけです。
1. ピーク要素とは、その値が左右の隣接する値よりも厳密に大きい要素を指します。厳密に以上
2. nums[-1] = nums[n] = −∞と仮定します。
3. すべての有効な i に対して、nums[i] != nums[i + 1] があります。
4. この問題を O(logN) 時間計算量で実装できますか?
データ範囲:
1≤数値.長さ≤2×105
−231<=nums[i]<=231−1
入力例:[2,4,1,2,7,8,4]
出力サンプル: 1
問題解決のアイデア:
1. 激しい列挙。前の桁より大きく、次の桁よりも大きい限り、それがピーク値であり、直接返されます。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int findPeakElement (int[] nums) {
// write code here
if(nums.length >= 2 && nums[0] > nums[1] || nums.length == 1){
return 0;
}
if(nums.length >= 2 && nums[nums.length-2] < nums[nums.length-1]){
return nums.length-1;
}
for(int i=1;i<nums.length-1;++i){
if(nums[i] > nums[i-1] && nums[i] > nums[i+1]){
return i;
}
}
return -1;
}
}
解決策のアイデア 2:
二分探索、実装時間の計算量は O(Logn)
通常の二分探索と同様に、mid が最初に計算されます。
nums[mid] > num[mid+1] の場合、mid がピーク値である可能性が高いことを意味するので、左に進みます。ここでの二分探索との違いは、左に進む場合、右 =mid、中間は可能であるため、中間 1 ではありません。ピーク値は次の巡回ラウンドで比較する必要があります。
nums[mid] <= nums[mid+1] の場合、mid+1 がピーク値である可能性が高いことを意味します。mid はピーク値の可能性がなくなったため、右、左 = Mid+1 に移動します。だから含めないでください
複数回のトラバースの後、最終的に間隔内で正しいピーク値を見つけることができます。
単調増加の場合は、left=right=nums.length-1 になるまで毎回右に移動し、単調減少の場合は、left=right=0 まで左に移動します。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int findPeakElement (int[] nums) {
// write code here
if(nums.length == 1){
return 0;
}
int left = 0;
int right = nums.length -1;
int mid;
while(left < right){
mid = (left + right) /2;
if(nums[mid] > nums[mid+1]){
//mid比下一位大,有可能是山峰,往左遍历
right = mid;//注意这里right是赋值mid,因为mid可能是山峰,所以要包含他去寻找
}else{
//mid比它下一位小,mid+1有可能是山峰,向右走
left = mid + 1;//从大的数开始往右查找
}
}
return right;
}
}
array_Niuke Topic_Niuke.com (nowcoder.com) 内の逆順序ペア
トピックの説明:
配列内の 2 つの数値で、最初の数値が後の数値より大きい場合、2 つの数値は逆順のペアを形成します。配列を入力し、配列内の逆順ペアの総数 P を求めます。そして、P モジュロ 1000000007 の結果を出力します。つまり、出力 P mod 1000000007
データ範囲: データの 50% の場合、サイズ ≤10^4
データの 100% の場合、サイズ ≤10^5配列内のすべての数値の値は 0≤val≤10^9 を満たします
要件: 空間計算量 O(n)、時間計算量 O(nlogn)
【入力例】[1,2,3,4,5,6,7,0]
【出力サンプル】7
問題解決のアイデア 1: 二重ループ、暴力的な列挙、時間計算量は O(n^2)、実行タイムアウト
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int InversePairs (int[] nums) {
// write code here
int ans=0;
for(int i =0; i<nums.length-1; ++i){
for(int j=i; j< nums.length; ++j){
if(nums[i] > nums[j]){
ans++;
ans %= 1000000007;
}
}
}
return ans;
}
}
解決策のアイデア 2:
マージソート方法に基づいて、マージ中に、右側の数が左側の数より小さい場合、現在生成されている逆順ペアの数を直接計算できます。
import java.util.*;
public class Solution {
int ans=0;
public int InversePairs (int[] nums) {
// write code here
if(nums.length < 2){
return 0;
}
mergeSort(nums,0,nums.length-1);
return ans;
}
public void mergeSort(int[] nums,int left,int right){
//分割点
int mid = (left+right)/2;
if(left < right){
mergeSort(nums,left,mid);
mergeSort(nums,mid+1,right);
//合并
merge(nums,left,mid,right);
}
}
public void merge(int[] nums,int left,int mid,int right){
//创建临时数组
int[] arr = new int[right - left + 1];
//临时数组下标起点
int c = 0;
int s = left;
int l = left;
int r = mid + 1;//左右数组的起始指针
while(l <= mid && r <= right){
//当左数组的元素小时,跳过
if(nums[l] <= nums[r]){
//放入临时数组
arr[c] = nums[l];
c++;
l++;
}else{
//存在逆序对,统计
arr[c] = nums[r];
//逆序对个数,
ans += mid+1 - l;
ans %= 1000000007;
c++;
r++;
}
}
//左子数组还有元素,放入
while(l <= mid){
arr[c++] = nums[l++];
}
while(r <= right){
arr[c++] = nums[r++];
}
//临时数组放入数组原位置
for(int num: arr){
nums[s++] = num;
}
}
}
回転配列の最小数_NiukeTiba_Niuke.com (nowcoder.com)
トピックの説明:
[1,2,3,4,5] など、長さ n の非降順配列があります。これを回転します。つまり、配列の最初の要素を配列の末尾に移動して、回転された配列にします。たとえば、[3,4,5,1,2]、または [4,5,1,2,3] になります。このような回転された配列が与えられた場合に、配列内の最小値を見つけてください。
データ範囲: 1≤n≤10000、配列内の任意の要素の値: 0≤val≤10000
要件: 空間計算量: O(1)、時間計算量: O(logn)
【入力例】[3,4,5,1,2]
【出力サンプル】1
問題解決のアイデア:
非降順配列を回転するには、二分探索を使用して配列を 2 つのサブ配列に分割します。順序が正しくないサブ配列が 1 つ存在する必要があります。
たとえば、[left, right] は [left, middle] [mid, right] に分割されます。nums[left] > nums[mid] の場合、[left, middle] 間隔が a の要件を満たしていないことがわかります。非降順配列なので、この間隔は回転後に無秩序になり、最小値がここで見つかります。
等しい場合は範囲を狭めて検索を続けます。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int minNumberInRotateArray (int[] nums) {
// write code here
int left = 0;
int right = nums.length-1;
while(left < right){
int mid = (left + right) / 2;
if(nums[mid] > nums[right]){ //右子数组无序
left = mid + 1;
}else if(nums[mid] < nums[right]){//左子数组无序
right = mid;
}else{
//如果是相等的话,缩小范围
right--;
}
}
return nums[left];
}
}