11. 最も多くの水を入れる容器
質問の意味:
n
length の整数配列が 与えられますheight
。n
垂線 があり 、i
その線の 2 つの端点は(i, 0)
と です(i, height[i])
。
x
軸とともに最も多くの水を保持できる容器を形成する2 本の線を見つけます 。コンテナが保存できる水の最大量を返します。
注:容器を傾けることはできません。
【入力サンプル】
[1,8,6,2,5,4,8,3,7]
【出力例】49
問題解決のアイデア: 長方形の最大面積を求めるために変換する
1. ダブル ポインタ i と j はそれぞれ配列の先頭と末尾を指し、i と j の間の距離が長方形の長さになります。
2. 長方形の高さは min(height[i],height[j]) です。
3. 見つけられる最大の領域を格納する変数を定義します。
乾燥開始
class Solution {
public int maxArea(int[] height) {
int i = 0,j = height.length - 1;
int maxWater = 0;
while(i<j){
//i不能等于j,等于j只是一条垂线,没有面积,没有办法盛水
maxWater = Math.max(maxWater,(j-i)* Math.min(height[i],height[j]));
if(height[i] < height[j]){
//当左边比右边小时,左指针i往右走,看在减少长度的时候,能不能增加高度
++i;
}else{
--j;
}
}
return maxWater;
}
}
タイム: 59.09% を達成
メモリ: 16.11% の差
15.3つの数字の合計
質問の意味:
整数配列が与えられた場合 、 および を 満たし 、 および も満たす
nums
トリプルがあるかどうかを判断します 。お願いします[nums[i], nums[j], nums[k]]
i != j
i != k
j != k
nums[i] + nums[j] + nums[k] == 0
0
合計が等しく、繰り返されないすべてのトリプルを返します 。注:回答に重複したトリプルを含めることはできません。
【入力サンプル】
数値=[-1,0,1,2,-1,-4]
[出力サンプル][[-1,-1,2],[-1,0,1]]
問題解決のアイデア: 並べ替え + ダブル ポインター
1. まず配列を昇順に並べ替えます(以下の a、b、c の値は添え字であることに注意してください)
2. a を列挙し、a を求めた後、残りの配列から b(a+1) と c(nums.length-1) を求め、3 つの足し算と 0 の関係を求めます。それらが等しい場合は、fill in この 3 つ組が結果に追加されます。0 より小さい場合は b++、右に移動して大きい方を見つけます。3 つの合計が 0 より大きい場合は、c を減らします。b と c の内部ループ終了条件は、a+b+c=0 ではなく b>=c です。これは、nums[a] が -3、nums[b]、nums[c など、複数の値が存在する可能性があるためです。 ] は -2 と 5、または -1 と 4 のいずれかになります。
3.a は、nums[a] 自体が 0 より大きくなり、ループが終了するまで列挙を続けます。
4. この質問では、繰り返しのトリプルを含めることはできません。a を決定するときは、nums[a-1] の値が nums[a] に等しいかどうかを判断する必要があります。等しい場合、その値は再度使用できません。トラバースを続けます。 bとcも同様です。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int a,b,c;
List<List<Integer>> result = new ArrayList<>();
for(a=0;a<nums.length;a++){
if(nums[a] > 0) break;
if(a > 0 && nums[a] == nums[a-1]) continue;//继续寻找下一个a
b = a+1;
c = nums.length-1;
while(b < c){
int sum = nums[a]+nums[b]+nums[c];
if( sum < 0){
++b;
}else if(sum > 0){
--c;
}else{
List<Integer> r1 = Arrays.asList(nums[a], nums[b], nums[c]);
result.add(r1);
while(b < c && nums[b] == nums[b+1]) ++b;
while(b < c && nums[c] == nums[c-1]) --c;
++b;
--c;
}
}
}
return result;
}
}
タイム: 91.31% を達成
メモリ: 64.32% 上回る
209.最小長のサブ配列
質問の意味:
n
正の整数の配列と正の整数 を指定しますtarget
。配列内でその合計を満たす最小の長さを持つ 連続した部分配列を見つけて 、その長さを返します。一致する部分配列がない場合は、 を返します 。
≥ target
[numsl, numsl+1, ..., numsr-1, numsr]
0
【入力サンプル】
ターゲット = 7、数値 = [2,3,1,2,4,3]
【出力サンプル】2
問題解決のアイデア:
暴力的な列挙です。質問の要件に注意してください。ターゲット以上であり、連続した部分配列です。
暴力的な列挙はタイムアウトになります。学習の参照のみを目的としています。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//注意求的是大于等于target,并且是一段连续的子数组
int result = nums.length + 1;
int sum = 0;//子序列的数值之和
int subLength = 0;//子序列的长度
for(int i=0;i<nums.length;++i){//子序列开始
sum = 0;
for(int j = i;j<nums.length;++j){//子序列结束
sum += nums[j];
if(sum >= target){
//更新结果
subLength = j-i+1;
result = result < subLength ? result : subLength;
break;//从下一个i继续找
}
}
}
return result == nums.length + 1 ? 0: result;
}
}
問題解決のアイデア:
ダブル ポインターを使用してスライディング ウィンドウ ソリューションを実装する
1. ポインタ j はウィンドウの終了位置を指します
2. ポインタ i はウィンドウの開始位置を指します。
3. j の位置を列挙し、それらを累積し続けます。sum が target 以上の場合、i を右に移動して、結果がまだ target より大きいかどうかを確認できます。i++ の前に sum-= があることに注意してください。 nums[i] が必要です。これは、右に 1 歩進んだ後、ウィンドウ内の合計に nums[i] が含まれないためです。
4. ウィンドウのスライド処理中、現在の状態の長さが結果より小さいかどうかを常に判断します。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//滑动窗口
//指针i指向窗口的左边,指针j指向窗口的右边
//根据窗口的和值是否大于target来判断是否要移动窗口看
int result = nums.length + 1;
int sum = 0;//子序列的数值之和
int subLength = 0;//子序列的长度
int i =0;//默认每次窗口的其实位置都是第一位
for(int j=0;j<nums.length;++j){//子序列开始
sum += nums[j];
while(sum >= target){
//当加起来的值大于目标值之后,可以判断此时i能不能往前滑动
subLength = j-i+1;
result = result < subLength ? result : subLength;
sum -= nums[i];
++i;//判断i往右滑动一步之后,是否还能符合条件,不能的话,内层while结束,外层j继续滑动
}
}
return result == nums.length + 1 ? 0: result;
}
}
時間: 99.69% を達成
メモリ: 57.73% の差
3. 重複する文字を含まない最長の文字列
質問の意味:
文字列を指定して 、繰り返し文字を含まない最長の部分文字
s
列の長さを 見つけてください 。
【入力サンプル】
s="abcabcbb"
【出力サンプル】3
問題解決のアイデア:
なぜなら、古典的な面接の質問 150 がスライディング ウィンドウにまとめられており、前回の質問 209 が私にとって初めてのスライディング ウィンドウの質問だったので、スライディング ウィンドウを使用して実装されるだろうとすぐに推測できました。
文字を繰り返さないでください。マップの使用を検討し、文字をキーとして使用してください。
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length()==0){
return 0;
}
int i=0;
int subLength = 0;
int result = 0;
Map<Character,Integer> map = new HashMap<>();
for(int j=0;j<s.length();++j){
char c = s.charAt(j);
while(map.containsKey(c)){
//如果map已经有这个字符了,左指针往右挪一步
//挪动前需要先删掉
map.remove(s.charAt(i));
++i;
}
map.put(c,j);
result = Math.max(result,j-i+1);
}
return result;
}
}
タイム: ビート 20.12%
メモリ: 41.36% の差