配列+二分法
番号35には
、並べ替えられた配列とターゲット値が与えられ、配列内でターゲット値を見つけて、そのインデックスを返します。ターゲット値が配列に存在しない場合は、挿入される位置を順番に返します。
配列に重複する要素はないと想定できます。
例1:
入力:[1,3,5,6]、5
出力:2
例2:
入力:[1,3,5,6]、2
出力:1
例3:
入力:[1,3,5,6]、7
出力:4
例4:
入力:[1,3,5,6]、0
出力:0
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/search-insert-position
著作権はLeetCodeが所有しています。商用転載の場合は、公認機関にご連絡ください。非商用転載の場合は、出典を明記してください。
package test;
import java.util.Scanner;
//编号35
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i]=scanner.nextInt();
}
int target = scanner.nextInt();
Main main = new Main();
System.out.println(main.searchInsert(a, target));
}
public int searchInsert(int[] nums, int target) {
int l = 0;
int r = nums.length-1;
int mid = 0;
while(l<=r) {
//不变量target在左闭右闭区间
mid = l+(r-l)/2;
if(nums[mid]>target) {
r=mid-1;
}else if (nums[mid]<target) {
l=mid+1;
}else {
return mid;
}
}
/**
* target是数组某个元素,所以return mid
* target在所有元素之前,跳出循环后left,right=>0,-1,所以return r+1
* target在所有元素之后,跳出循环后left,right=>right,left,所以return r+1
* target在插入数组之间,跳出循环后left,right=>right,left,所以return r+1
*
*/
return r+1;
}
}
アレイを所定の位置で操作する
数値27
は、numの配列とvalの値を示します。値がvalと等しいすべての要素を削除し、削除された配列の新しい長さを返す必要があります。
余分な配列スペースは使用しないでください。O(1)の余分なスペースのみを使用し、入力配列をその場で変更する必要があります。
要素の順序は変更できます。新しい長さを超える配列内の要素を考慮する必要はありません。
説明:
戻り値が整数なのに、出力の答えが配列であるのはなぜですか?
入力配列は「参照」によって渡されることに注意してください。これは、関数内の入力配列の変更が呼び出し元に表示されることを意味します。
あなたは次のように内部操作を想像することができます:
// numsは「参照」によって渡されます。つまり、実際のパラメーターのコピーを作成しないでください
int len = removeElement(nums、val);
//関数の入力配列の変更は、呼び出し元に表示されます。
//関数によって返される長さに応じて、その長さの範囲内の配列内のすべての要素が出力されます。
for(int i = 0; i <len; i ++){ print(nums [i]); }
例1:
入力:nums = [3,2,2,3]、val = 3
出力:2、nums = [2,2]
説明:関数は新しい長さ2を返す必要があり、numsの最初の2つの要素は両方とも2です。新しい長さを超える配列内の要素を考慮する必要はありません。たとえば、関数によって返される新しい長さは2であり、nums = [2,2,3,3]またはnums = [2,2,0,0]も正解と見なされます。
例2:
入力:nums = [0,1,2,2,3,0,4,2]、val = 2
出力:5、nums = [0,1,4,0,3]
説明:関数は新しいものを返す必要があります長さ5、numsの最初の5つの要素は0、1、3、0、4です。これらの5つの要素は任意の順序にすることができることに注意してください。新しい長さを超える配列内の要素を考慮する必要はありません。
促す:
0 <= nums.length <= 100 0 <= nums
[i] <= 50
0 <= val <= 100
出典:LeetCode(LeetCode)
リンク:https ://leetcode-cn.com/problems/remove-element
著作権はLeetCodeが所有しています。商用転載の場合は、公認機関にご連絡ください。非商用転載の場合は、出典を明記してください。
解決策1:並べ替え
package test;
import java.util.Arrays;
import java.util.Scanner;
public class Main1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i]=scanner.nextInt();
}
int val = scanner.nextInt();
Main1 main = new Main1();
System.out.println(main.removeElement(a, val));
}
public int removeElement(int[] nums, int val) {
int count=0;
for (int i = 0; i < nums.length; i++) {
if(nums[i]==val) {
count++;
nums[i]=Integer.MAX_VALUE;
}
}
Arrays.sort(nums);
return nums.length-count;
}
}
解決策2:ダブルポインター
package test;
import java.util.Arrays;
import java.util.Scanner;
public class Main1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i]=scanner.nextInt();
}
int val = scanner.nextInt();
Main1 main = new Main1();
System.out.println(main.removeElement2(a, val));
}
public int removeElement2(int[] nums, int val) {
int slowIndex = 0;//指向非目标值元素
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if(val!=nums[fastIndex]) {
nums[slowIndex++]=nums[fastIndex];
}
}
return slowIndex;
}
}
最小のサブアレイ
番号209には
、n個の正の整数と正の整数のターゲットを含む配列が与えられます。
配列内の合計≥ターゲットを満たす最小の長さの連続サブ配列[numsl、numsl + 1、…、numsr-1、numsr]を見つけて、その長さを返します。条件を満たすサブ配列がない場合は、0が返されます。
例1:
入力:target = 7、nums = [2,3,1,2,4,3]
出力:2
説明:サブ配列[4,3]は、この条件下で長さが最小のサブ配列です。
例2:
入力:target = 4、nums = [1,4,4]
出力:1
例3:
入力:target = 11、nums = [1,1,1,1,1,1,1,1]
出力:0
促す:
1 <=ターゲット<= 109
1 <= nums.length <= 105
1 <= nums [i] <= 105
上級:
O(n)時間計算量のソリューションを実装した場合は、O(n log(n))時間計算量のソリューションを設計してみてください。
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/minimum-size-subarray-sum
著作権はLeetCodeが所有しています。商用転載の場合は、公認機関にご連絡ください。非商用転載の場合は、出典を明記してください。
暴力法、ダブルサイクル
package lk2021_03_17;
import java.util.Scanner;
//编号209
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i]=scanner.nextInt();
}
int target = scanner.nextInt();
Main main = new Main();
System.out.println(main.minSubArrayLen(target, a));
}
public int minSubArrayLen(int target, int[] nums) {
int res=Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
int sum=0;
int count=0;
for (int j = i; j < nums.length; j++) {
sum+=nums[j];
if(sum>=target) {
count=j-i+1;
res=Math.min(res, count);
break;
}
count++;
}
}
return res==Integer.MAX_VALUE?0:res;
}
}
解決策2、スライディングウィンドウ
package lk2021_03_17;
import java.util.Scanner;
public class Main2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i]=scanner.nextInt();
}
int target = scanner.nextInt();
Main2 main = new Main2();
System.out.println(main.minSubArrayLen(target, a));
}
public int minSubArrayLen(int target, int[] nums) {
int res = Integer.MAX_VALUE;
int sum=0;//窗口总和
int i=0;//窗口起始位置
for (int j = 0; j < nums.length; j++) {
sum+=nums[j];
while(sum>=target) {
int len=j-i+1;//子序列长度
res=res>len?len:res;//取较小值
sum-=nums[i++];//起始位置变化
}
}
return res==Integer.MAX_VALUE?0:res;//对Integer.MAX_VALUE结果处理
}
}
スパイラルマトリックスII
正の整数nを指定して、1からn2までのすべての要素を含むnxn正方行列行列を生成します。要素は、時計回りにらせん状に配置されます。
例1:
入力:n = 3
出力:[[1,2,3]、[8,9,4]、[7,6,5]]
例2:
入力:n = 1
出力:[[1]]
促す:
1 <= n <= 20
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/spiral-matrix-ii
著作権はLeetCodeが所有しています。商用転載の場合は、公認機関にご連絡ください。非商用転載の場合は、出典を明記してください。
シミュレーション、円で印刷
package lk2021_03_17;
import java.util.Arrays;
public class Main3 {
public static void main(String[] args) {
Main3 main3 = new Main3();
int[][] res=main3.generateMatrix(3);
for (int[] is : res) {
System.out.println(Arrays.toString(is));
}
}
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
int startx=0,starty=0;//定义起始位置
int loop=n/2;//循环圈数
int mid=n/2;//矩阵中间位置,n为奇数时单独填充
int count=1;//起始数字
int offset=1;//偏移量
int i,j;
while (loop-->0) {
i=startx;
j=starty;
//左到右
for (j = starty; j < starty+n-offset; j++) {
res[startx][j]=count++;
}
//上到下
for (i = startx; i < startx+n-offset; i++) {
res[i][j]=count++;
}
//右到左
for (; j > starty; j--) {
res[i][j]=count++;
}
//下到上
for (; i > startx; i--) {
res[i][j]=count++;
}
//下一层
startx++;
starty++;
offset+=2;
}
//n为奇数单独填充中间
if(n%2!=0) {
res[mid][mid]=count;
}
return res;
}
}