[21/08/16 KATA NINJA] leetcode #1
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
for(let check=0;check<nums.length;check++){
const first = nums[check]
for(let check1=check+1;check1<nums.length;check1++){
const second = nums[check1]
if(first+second===target) return [check,check1]
}
}
};
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
let answer = []
const numsIdx = nums.map((i,idx)=>idx)
function DFS(array,r){
if(r === 1){
return array.map(i=>[i]);
}
let result = []
array.forEach((i,idx) => {
const dfs = DFS(array.slice(idx+1),r-1);
const s = dfs.map(a => [i,...a]);
result.push(...s);
})
return result;
}
const combination = DFS(numsIdx,3);
combination.forEach(i=>{
let result = 0;
let array = []
i.forEach(a=>{
result += nums[a];
array.push(nums[a]);
})
if(result === 0){
array = array.sort((a,b)=>a-b);
answer[`${array[0]}${array[1]}${array[2]}`] = array;
}
})
return Object.keys(answer).map(key=>answer[key]);
};
上記のように、答えは正しいですが、タイムアウトもあります.この問題は二重ポインタアルゴリズムで解決しなければならない.
ダブルポインタ復習
名前の通り、2つのポインタを使用して放出する方法=>完全に時間を短縮できます.
2つのアレイの整列と結合
[1,5,6]
[2,8]
このパラメータが与えられている場合、問題は=>[1,2,5,6,8]に設定されます.
下のように解くことはできません.sort自体の複雑さはO(nlogn)である.
function solution(arr1, arr2) {
return [...arr1, ...arr2].sort();
}
下図のようにO(n+m)で終わることができます.
function solution(arr1, arr2) {
let answer = [];
let p1 = 0;
let p2 = 0;
while (p1 !== arr1.length && p2 !== arr2.length) {
answer.push(arr1[p1] > arr2[p2] ? arr2[p2++] : arr1[p1++]);
}
return p1 === arr1.length
? [...answer, ...arr2.slice(p2)]
: [...answer, ...arr1.slice(p1)];
}
公共の要素を求めます
[1,2,3,4,5]
[3,4,5,6,7]
=>3,4,5が与えられた場合、ダムを選択します.
解はBABOです.filterもすべての要素を巡回し,includeもすべての要素を巡回するのでO(n^2)となる.
return arr2.length > arr1.length
? arr2.filter((_) => arr1.includes(_))
: arr1.filter((_) => arr2.includes(_));
2つのポインタで緩めます.次のようにします.function solution(arr1, arr2) {
let answer = [];
let p1 = 0;
let p2 = 0;
// 우선 소팅을 해준다.
arr1.sort((_, __) => _ - __);
arr2.sort((_, __) => _ - __);
// 양쪽을 순회하면서 작은 쪽의 값을 올려준다.
// 소팅이 되어있으므로, 작은 값을 올리게 되면 큰 값과 비교했을 때 같은 값이 나올 수 있다.
// 큰 값을 올리게되면, 죽어도 같은 값은 나올 수 없다. (순회 끝까지 가더라도)
while (p1 !== arr1.length && p2 !== arr2.length) {
if (arr1[p1] === arr2[p2]) {
answer.push(arr1[p1]);
p2++;
p1++;
} else {
arr1[p1] > arr2[p2] ? p2++ : p1++;
}
}
console.log(answer);
}
部分数列の和
[1,2,1,3,1,2]および6
2つのポインタで解くことができます.
let p1 = 0;
let p2 = 0;
let answer = [];
while (p1 !== arr.length && p2 !== arr.length) {
const result = arr.slice(p1, p2 + 1).reduce((a, b) => a + b);
if (result > m) {
// 모두 더한 값이 크면, 왼쪽포인터 값을 올려야 한다. 크기 때문에 더 값을 더해봤자 의미 없다.
p1++;
} else {
if (result === m) {
// 모두 더한 값이 같다면, 왼쪽 포인터 값을 올린다. 마찬가지로 값을 더해봤자 m은 나올 수 없다.(양수만 있다고 가정하면)
answer.push(arr.slice(p1, p2 + 1));
p1++;
} else {
// 값이 더 작다면, 오른쪽 포인터 값을 올린다. 오른쪽 값을 올리게되면 m이 나올 수 있다.
p2++;
}
}
}
部分数列の和が特定の値を下回る
その名の通り、特定値以下の部分数列の個数を求めればよい.
function solution(arr, m) {
// 갯수를 구하는 것이기 때문에 야매로
let p1 = 0;
let p2 = 0;
let answer = 0;
while (p1 !== arr.length && p2 !== arr.length) {
const result = arr.slice(p1, p2 + 1).reduce((a, b) => a + b);
if (result <= m) {
answer += p2 - p1 + 1;
p2++;
} else {
p1++;
}
}
return answer;
}
console.log(solution([1, 3, 1, 2, 3], 5));
Reference
この問題について([21/08/16 KATA NINJA] leetcode #1), 我々は、より多くの情報をここで見つけました https://velog.io/@rat8397/210816-KATA-NINJA-leetcode-1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol