알고리즘 2일차

개발 log·2021년 8월 2일
0

알고리즘

목록 보기
9/11

1, 2차원 배열탐색과 시뮬레이션

문자열은 효율성을 크게 신경 쓰지 않아도 된다
그래도 최선을 다하자




수열축소

  1. m만큼 축소할 것이기 때문에 m만큼 반복하는 반복문 생성
  2. 내부에 nums배열을 돌며 뒤의 값과 앞의 값의 차를 앞의 위치에 할당
  3. 이렇게 하면 배열의 앞부분에는 m만큼 반복된 축소수열의 값이 들어있고
  4. 뒷부분에는 본래의 값이 들어있다
  5. 반환할 때는 m길이만큼 slice한 값 반환
function solution(nums, m) {
  let answer;
  let n = nums.length;
  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n - i - 1; j++) {
      nums[j] = nums[j + 1] - nums[j];
    }
  }
  answer = nums.slice(0, n - m);
  return answer;
}

가장 높은 증가수열

  1. 1번 인덱스부터 반복문을 돌리며 앞의 값과 비교하며 진행
  2. 만약 오른쪽값이 더 크다면 heigth변수에 높이값 추가할당
  3. 그렇지 않다면 answer에 height값과 비교하여 큰 값을 할당
  4. height 초기화
  5. 반복문이 돌때마다 answer값과 height값을 비교하여 큰 값을 할당
  6. answer 반환
function solution(nums) {
  let answer = 0;
  let heigth = 0;
  for (let rt = 1; rt < nums.length; rt++) {
    if (nums[rt - 1] < nums[rt]) heigth += nums[rt] - nums[rt - 1];
    else {
      answer = Math.max(answer, heigth);
      heigth = 0;
    }
    answer = Math.max(answer, heigth);
  }
  return answer;
}

가장 긴 수열

  1. 증가수열을 카운트하는 up변수와 감소수열을 카운트하는 down변수를 생성
  2. 반복문을 돌리며 증가, 감소수열 카운트하며 max값을 max변수에 할당
  3. 반복문이 끝난 후 max값을 max변수에 할당
  4. 마지막으로 answer에 증가수열과 감소수열의 카운트 중 최대값을 할당하여 반환
function solution(nums) {
  let up = 1,
    down = 1,
    maxup = 0,
    maxdown = 0;
  for (let i = 1; i < nums.length; i++) {
    if (nums[i - 1] < nums[i]) up++;
    else (maxup = Math.max(maxup, up)), (up = 1);
    if (nums[i - 1] > nums[i]) down++;
    else (maxdown = Math.max(maxdown, down)), (down = 1);
  }
  maxup = Math.max(maxup, up);
  maxdown = Math.max(maxdown, down);
  let answer = Math.max(maxup, maxdown);

  return answer;
}

바이토닉 수열

  1. 반복문을 한번 돌려서 증가수열이 있는지 카운트한다
  2. (배열길이보다 짧고 i인덱스에 있는 값이 더 작다면)
  3. 반복문을 한번 돌렸는데 카운트가 0(증가수열이 없다)이거나 배열길이만큼 카운트 됐다면
  4. answer에 'NO'할당
  5. 반복문을 카운트된 i값(해당값이 증가수열의 마지막 값)부터 시작하여 감소수열을 탐색
  6. 만약 카운트가 끝난 값이 배열 끝에 있는 값이 아니라면 'NO'반환
  7. if 문에 걸리지 않았다면 'YES' 반환
function solution(nums) {
  let answer = "YES";
  let n = nums.length;
  let i = 0;

  while (i + 1 < n && nums[i] < nums[i + 1]) i++;
  if (i === 0 || i === n - 1) answer = "NO";
  while (i + 1 < n && nums[i] > nums[i + 1]) i++;
  if (i !== n - 1) answer = "NO";
  return answer;
}

거리두기

  1. nums 배열을 돌며 자리가 비어있다면 cnt를 올리고
  2. peek변수보다 cnt가 크다면 peek에 cnt를 할당
  3. 자리가 비어있지 않다면 cnt = 0
  4. 비어있는 자리가 시작점이나 끝점에 있을 경우
  5. 시작점이나 끝점에서 시작하는 자릿수가 더 많은 경우 값 그대로 반환
  6. 아닐 경우 비어있는 자릿값 / 2를 올림한 값을 반환
function solution(nums) {
  let peek = 0,
    cnt = 0,
    cnt2 = 0;
  nums.forEach((n) =>
    n === 0 ? (cnt++, peek < cnt ? (peek = cnt) : false) : (cnt = 0)
  );
  if (nums[0] === 0 || nums[nums.length - 1] === 0) {
    for (let i = 0; i < nums.length; i++) {
      if (nums[i] === 0) cnt2++;
      else break;
    }
    peek = Math.max(peek, cnt2);
    cnt2 = 0;
    for (let i = nums.length - 1; i > 0; i--) {
      if (nums[i] === 0) cnt2++;
      else break;
    }
    peek = Math.max(peek, cnt2);
  }
  return parseInt(peek / 2);
}

2차원 배열 1의 개수

  1. map함수와 reduce함수를 이용해 배열의 인덱스와 1의 개수가 담긴 배열을 반환한 후
  2. sort함수로 개수기준으로 오름차순으로 정렬하여
  3. map함수로 인덱스값으로 정렬된 배열 반환
function solution(nums) {
  const arr = nums.map(
    (n, i) => (n = [i, n.reduce((acc, current) => acc + current)])
  );
  arr.sort(([, a], [, b]) => a - b);
  return arr.map((e) => e[0]);
}

행과 열의 최솟값

  1. 반복문을 돌며 min 변수에 각 행의 0번째 인덱스값을 할당
  2. 이중 반복문을 통해 각 행의 최솟값을 찾고 pos변수에 인덱스를 할당
  3. 다른 이중 반복문을 돌며 row행의 pos번째에 있는 값과 min을 비교하여 할당
  4. 반복문이 돌때마다 row가 배열의 길이만큼 돌았다면 answer에 min값 push
  5. 반복문이 끝나면 answer을 정렬하여 반환
function solution2(nums) {
  let answer = [];
  let n = nums.length;
  for (let i = 0; i < n; i++) {
    let min = nums[i][0];
    let pos = 0;
    for (let j = 0; j < n; j++) {
      if (nums[i][j] < min) {
        min = nums[i][j];
        pos = j;
      }
    }
    let row;
    for (row = 0; row < n; row++) {
      if (nums[row][pos] < min) break;
    }
    if (row == n) answer.push(min);
  }
  answer.sort((a, b) => a - b);
  return answer;
}

봉우리

  1. 각 봉우리의 동서남북을 탐색하는 인덱스값을 가진 dx, dy 배열 생성
  2. 이중 반복문을 돌며 flag변수를 세운 뒤
  3. 4방위를 도는 반복문생성
  4. 4방위를 돌며 봉우리값보다 큰값이 있다면 flag변수에 false할당하고 break
  5. flag가 true인 경우만 answer에 ++
  6. 반복문이 끝난 뒤 answer 반환
function solution3(nums) {
  let answer = 0;
  let n = nums.length;
  let dx = [-1, 0, 1, 0];
  let dy = [0, 1, 0, -1];
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      let flag = true;
      for (let k = 0; k < 4; k++) {
        let nx = i + dx[k];
        let ny = j + dy[k];
        if (
          nx >= 0 &&
          nx < n &&
          ny >= 0 &&
          ny < n &&
          nums[nx][ny] >= nums[i][j]
        ) {
          flag = false;
          break;
        }
      }
      if (flag) answer++;
    }
  }
  return answer;
}

QUIZ: 바이토닉 수열 탐색

  1. arr의 길이만큼 0으로 채운 배열 dist와 ch 생성
  2. ch[0]에 1할당하고
  3. d변수에 1을 할당하고
  4. 반복문 시작
  5. 앞에서부터 증가수열을 탐색하여 d값에 카운트
  6. 카운트된 값을 dist의 i인덱스에 지속적으로 할당
  7. 증가수열이 아니라면 d를 1로 초기화하고 ch[i]에 1 할당
  8. 증가수열을 탐색하는 반복문이 끝나면 다시 d를 1로 초기화하고 ch[배열끝]에 1할당
  9. 배열 끝에서 부터 시작점까지 증가하는 수열을 탐색하여 앞의 과정 반복
  10. 탐색하는 반복문이 모두 끝나면 ch[i]가 0이고(1은 증가수열이 끊긴 지점)
  11. dist[i]-1이 answer보다 크다면
  12. answer에 dist[i]-1을 할당하는 반복문을 실행하고
  13. 끝나면 answer 반환
function solution(arr) {
  let answer = 0;
  let n = arr.length;
  let dist = Array.from({ length: n }, () => 0);
  let ch = Array.from({ length: n }, () => 0);
  ch[0] = 1;
  let d = 1;
  for (let i = 1; i < n; i++) {
    if (arr[i - 1] < arr[i]) {
      d++;
      dist[i] = d;
    } else {
      d = 1;
      ch[i] = 1;
    }
  }
  d = 1;
  ch[n - 1] = 1;
  for (let i = n - 2; i >= 0; i--) {
    if (arr[i] > arr[i + 1]) {
      d++;
      dist[i] += d;
    } else {
      d = 1;
      ch[i] = 1;
    }
  }
  for (let i = 0; i < n; i++) {
    if (ch[i] === 0 && dist[i] - 1 > answer) {
      answer = dist[i] - 1;
    }
  }
  return answer;
}
profile
프론트엔드 개발자

0개의 댓글