211006_자료구조&알고리즘(2)

nais·2021년 10월 6일
0

네카라쿠배

목록 보기
16/27

1. 1차원 배열을 이용한 문제풀이

(1). 수열축소

🔥길이가 n 인 수열이 주어지면 두 수의 차이를 이용해 길이가 n-1 인 수열을 만든다.
n길이의 수열이 주어지면 m번의 길이 축소 작업한 결과 출력하기

  • 간단하게 for문만 사용하면 된다

  • 첫번째 for문 -> m번의 길이 축소 작업 횟수

  • 두번째 배열의 길이 ((n-1) - 축소 작업 횟수)

  • slice 사용하여 n-m 번까지만 출력해준다

function solution1(nums, m){

  let answer;

  let n = nums.length;
 
  for(let i = 0; i < m ; i++){ // m 번의 축소 작업 for문 
    for(let j = 0 ; j < n-i-1 ; j++){
      nums[j] = nums[j+1] - nums[j];
    }
  }

  answer = nums.slice(0,n-m);

  return answer;
}
console.log(solution1([5,3,7,9,-2], 1));

(2). 제곱수 정렬

오름차순 정렬되어 있는 길이가 n인 수열
이 수열들을 제곱해서 오름차순으로 정렬하라

  • 이미 오름차순으로 정렬이 되어있다는 것은
    O(n) 으로 풀어야 한다는 것을 의미

  • left , right 포인터로 처음 과 맨 끝의 값들의 절대값 math.abs()로 비교하라

  • 값이 큰 것 부터 배열에 넣어준다

function solution2(nums){

  let n = nums.length;
  let answer = new Array(nums.length).fill(0);

  let left = 0, right = n-1 ,tmp ;

  for( let i = n-1; i >=0; i--){
    if(Math.abs(nums[left]) < Math.abs(nums[right])){
      tmp = nums[right];
      right--;
    }
    else{
      tmp = nums[left];
      left++;
    }
    answer[i] = tmp * tmp;
  }

  return answer;
  }

  console.log(solution2([-4,-1,0,3,10]));

(3). 수열의 높이 조정

N의 길이 수열이 주어지고 열의 원소 값 중 가장 큰 원소에서 1을 뺸 값을 가장 작은 원소에 더해주고 m회 거쳐가장 큰값- 작은 값 차 구하기

  • 수열 원소는 1000을 넘지 않으니 1000사이즈의 배열을 만들어서 원소 자체가 배열의 인덱스 값이 되어서 카운트 해주는 배열 생성

  • 이 카운트값이 1인 경우에로 판단한다 (ex. 가장 작은 수 값 2의 카운트가 1이라면 이 경우에는 최소값도 바뀌기 때문이다!

function solution3(nums,m){

  let answer = 0;

  let chArr = new Array(1000).fill(0);

  let maxH = Number.MIN_SAFE_INTEGER; // 안전한 최대 정수값 선언

  let minH = Number.MAX_SAFE_INTEGER; // 안전한 최소 정수값 선언


  // chArr 배열을 선언하여 갯수를 카운트 해주고 최대, 최소값 세팅
  for (let x of nums){
    chArr[x]=+1;
    if( x < minH) minH = x;
    if( x > maxH) maxH = x;
  }

  for(let i = 0; i<m ; i++){
      if(maxH === 1 && minH === 1) return 0;
      
      if(chArr[minH] ===1){
        chArr[minH]--;
        minH++;
        chArr[minH]++;
      }
      else{
        chArr[minH]--;
        chArr[minH+1]++;
      }
      if(chArr[maxH]===1){
        chArr[maxH]--;
        maxH--;
        chArr[maxH]++;
        
      }
      else{
        chArr[minH]--;
        chArr[minH-1]++;
      }

    }
      
    answer = maxH - minH;
  return answer;
}

(4) 가장 높은 증가 수열

길이가 주어진 N 수열에서 연속된 부분 증가 수열을 찾는다 증가수열의 높이란 증가수열 중 첫항과 마지막항의 차를 의미

  • n과 n-1을 비교 n이 n-1보다 크면 증가 수열로 본다 그래서 높이를 height 에 저장
  • 그렇지 않은 경우에는 (다시 감소되는 부분을 만나면 ) answer 에 증가 부분 계산되었던걸 저장한다
function solution4(nums){
  let answer = 0;
  let height = 0;

  for(let i = 1 ; i < nums.length ; i++){
    if( nums[i-1] < nums[i] ){ //증가수열이라면?
      height +=nums[i] - nums[i-1]; 
    }
    else{
      answer = Math.max(height,answer);
      height = 0;
    } //감소 하는 부분이라면 이전에 기록해주던 증가수열 값과 그 값을 백업해둔 answer 중 큰 값을 저장
  }

  //수열을 다 확인해서 봤다면 이전에 저장해둔 증가수열과, 다시 측정된 증가수열 부분 중 더 큰 값 리턴
  answer = Math.max(height,answer);
  return answer;

}

(5) 가장 긴 수열

수열에서 연속으로 증가하거나 또는 연속으로 작아지는 부분 중 가장 길이가 긴 수열을 찾아라

  • 길이를 측정하는 것이기 때문에 up =1 , down = 1 로 선언

  • 상승값과 감소값 두 가지 다 반복문 안에서 돌다가 감소 -> 상승, 상승 -> 감소의 구간이 생기면 새로 측정된 값과 이전의 값중 더 큰 것을 maxup 과 maxdown 에 기록해준다

function solution5(nums){

  let answer = 0;
  let count = 0;

  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(up,maxup);
      up=1;
    }
    //감소로 전환
    if(nums[i-1] > nums[i]){
      down++;
    }
    else{
      maxdown=Math.max(down,maxdown);
      down=1;
    }
  }
    maxup = Math.max(up,maxup); //상승 타다가 하강 발견
    maxdown=Math.max(down,maxdown);
    answer = Math.max(maxup,maxdown);
    return answer;

}

(6) 바이토닉

  • 바이토닉 수열이란 수열이 증가했다가 감소하는 수열을 의미 연속된 값이 있는 것은 바이토닉이라고 하지 않는다

  • while 문 쓰면 쉬운건데 나는 무조건 for 문만 돌리려고 하는 나쁜 버릇이 있다는걸 발견

function solution6(nums){

    let answer ='YES';
    let i= 0;
    let n  = nums.length;

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

    return answer;
  }

  console.log(solution6([1,2,3,4,5]));

(7) 거리두기

현수가 영화관에 앉아있는 사람들과 최대한 멀리 앉을 수있는 거리(내가 이해한 문제 바로는 좌석의 시작 부분과 가깝지만 사람과는 최대한 먼 자리 선택) 으로 이해해야지 약간 머리가 돌아가더라.. 왼쪽 오른쪽 중에 어디가 좋을까 이거 아닌가?

  • 1차원 배열을 하나 선언하고 그 안에 해당 인덱스 번호의 좌석이 사람과 얼마나 거리를 두고 앉아있는지 체크

  • 왼쪽 한번 for으로 돌면서 사람이 앉아있는 자리와 비어있는 자리의 간격의 값을 넣어준다

  • 오른쪽 for로 돌 때는 배열에 값을 넣어줄 때 가깝지만 가장 가까운 사람과의 값도 생각해야 하기때문에 왼, 오 둘 중에 작은 값을 넣어준다

  • 다 넣어주고서 가장 멀리 떨어져있는 d 의 값이 제일 큰 것을 골라서 리턴

function solution7(nums){

  let answer = 0;


  let dist = new Array(100).fill(0);

  let d = 100;
  for(let i  = 0; i <nums.length; i++ ){

    if(nums[i] === 1){ //사람이 있다면 
      d = 0; // 거리는 0 
      dist[i] = d;
    }
    else{
      d++;
      dist[i] = d;
    }
  }

  d = 100;
  for(let i = nums.length -1  ; i >= 0 ; i-- ){
      if(nums[i] === 1){
        d = 0 ; 
      }
      else{
        d++;
        dist[i] = Math.min(dist[i],d);
      }
    }
    answer = Math.max(...dist); // 스프레드 연산자 
    return answer;
  }

📌 스프레드 연산자
1.배열
(1)배열에서의 스프레드 연산자는 병합의 의미이다 기존의 배열들의 값을 병합해서 출력할수 있음
(2) 배열의 복사도 가능하다

let arr1 = ["철수","영희"];
let arr2 = [...arr1];
console.log(arr2) // ["철수","영희"]
-> 얕은 복사로서 객체 자체가 복사되는 것은 아님
  1. 함수
    (1) 함수 호출시에 함수의 매개변수로 작성한 형테 파라미터로 오는 값들을 모아서 배열에 집어 넣는 다는 표현이다
function add(...rest){
}
console.log(add(1,2,3)) // 6이 들어가게됨 

(2) 함수의 호출 인자로 사용
🔥우리가 사용한 형태, 기존에는 배열로 되어있는 내용을 함수의 인자에 사용할 수있는 것이다. 잘 알아두자

(8) 빈도수 구하기

길이가 N인 수열 자연수 K가 주어지면 수열의 원소 중 빈도수가 가장 많은 순으로 k 개를 찾아주는 것

  • 해싱으로 수열 원소 빈도 수 구하기

  • map정렬하는데 일반적인 sort는 사용이 불가능하다

  • [...hash].sort((a,b) => b[1]-a[1]) value 값으로 내림차순 정렬 , 오름차순은 a[1]-b[1]

function solution8(nums,k){

  let answer =[];

  let hashArray = new Map();

  for (let x of nums){

    hashArray.set(x,(hashArray.get(x) || 0) +1);
  }

  let tmp = [...hashArray].sort((a,b) => b[1] - a[1]);
 
  for(let i =0 ; i<k ; i++){
    answer.push(tmp[i][0]);
  }

  return answer;
}
console.log(solution8([3,3,3,5,1,1,1,7,2,2],3));

javascripts - set

  • set은 value 만을 저장하며 중복을 허용하지 않는 collection

  • 생성자 : new Set();

  • 개수확인: Set.size;

  • 요소 추가: Set.add(value);

  • 요소 삭제:set.delete(value);

  • 전체 삭제 : set.clear();

  • 요소 존재 여부 확인: Set.has(key)

  • 그 밖의 메서드 set.keys(), set.values() , set.entires()

profile
왜가 디폴트값인 프론트엔드 개발자

0개의 댓글