반응형

 

Cascading 이란?
Cascade사전적 의미를 찾아보면, "폭포가 되어 떨어지다.", "폭포처럼 떨어뜨리다." 등의
위에서 아래로 흐른다는 의미를 가지고 있다.

이처럼 CSS에서는 폭포처럼 스타일 규칙이 계단식으로 적용된다.
이런 스타일 규칙은 여러 개가 HTML 요소에 적용될 수 있는데,
이를 우선순위에 따라 결정하는 것을 "Cascading"이라고 한다.

 

그럼 저 우선순위는 어떻게 결정할까?

 

우선 순위

 

기본적으로 우선 순위를 결정할 때는 명시도를 고려해야하는데, 선택자마다 명시도 점수가 있다.

 

① id

② 클래스, 속성, 가상(pseudo)클래스

③ 태그, 가상(psuedo)요소

- 태그 < class < id 순으로 우선순위가 높으며, 각각의 개수를 비교하여 우선순위가 결정된다.

tag#id {  ···  }             /* --- 점수 : 1 0 1 --- */  1순위
tag.class {  ···  }          /* --- 점수 : 0 1 1 --- */  3순위
.class {  ···  }             /* --- 점수 : 0 1 0 --- */  4순위
tag.class1.class2 {  ···  }  /* --- 점수 : 0 2 1 --- */  2순위

 

명시도 점수 외에도 고려할 점들이 있다.

 

1. !important: 명시도와 무관하지만 명시도에 직접 영향을 미치고 다른 선언보다 우선한다.

   * important가 여러 개일 경우에는 명시도 점수가 높은 것부터 우선순위로 적용된다.

2. 인라인 스타일 정의: 인라인 스타일은 항상 외부 스타일시트의 모든 스타일을 덮어쓰기때문에 가장 높은 명시도를 갖는다.

3. 상속된 스타일

     : 부모 태그에 적용된 CSS 규칙은 자손에게도 상속된다.

       모든 속성이 상속되는 건 아니고, 상속되는 속성(color, font-family 등)들이 정해져 있다.

       조상 태그들의 스타일이 모두 계산된 상태에서 우선순위를 따지는데, 가까운 조상에게 물려받은 속성일수록 우선순위가 높다.

4. 코드 상의 순서: 동일한 가중치를 갖는 규칙이 두 개 이상인 경우, 코드에서 아래 쪽에 쓴 코드일수록 우선순위가 높다.

<style>
    p {
      color: blue;
      color: red;  /* -- 적용되는 스타일 -- */
  </style>

 


 

또한 스타일 시트가 상호 충돌할 경우, 우선 적용되는 순서는 아래와 같다.

 

1. 웹 페이지를 만든 저자가 작성한 스타일 시트 = 개발자 스타일 시트 : 개발자 스타일 시트 안에서도 적용되는 우선 순위가 있다.

     1) 인라인 스타일: HTML 요소의 style 속성으로 지정된 스타일

<body>
  <p style="color: red"> Hello, World! </p>
</body>

 

     2) 내부 스타일: HTML 문서 내 <head> → <style> 태그 내 선언

<head>
  <style>
    p {
      color: red;
      }
  </style>
</head>

 

     3) 외부 스타일: 외부 css 파일

 

2. 사용자가 작성한 스타일 시트

3. 브라우저에서 기본으로 제공하는 스타일시트

 


 

종합적으로 위의 규칙들이 적용되는 순서는 상속된 스타일 < 명시도 < 인라인 스타일 <​ !important의 순서로 적용된다.

 

하지만 !important와 인라인 스타일의 경우, 스타일 디버깅을 어렵게 하므로 되도록 사용하지 않는 것이 좋다!

반응형
반응형
문제:
짝지어 제거하기는, 알파벳 소문자로 이루어진 문자열을 가지고 시작합니다.
먼저 문자열에서 같은 알파벳이 2개 붙어 있는 짝을 찾습니다. 그다음, 그 둘을 제거한 뒤, 앞뒤로 문자열을 이어 붙입니다.
이 과정을 반복해서 문자열을 모두 제거한다면 짝지어 제거하기가 종료됩니다.
문자열 S가 주어졌을 때, 짝지어 제거하기를 성공적으로 수행할 수 있는지 반환하는 함수를 완성해 주세요.
성공적으로 수행할 수 있으면 1을, 아닐 경우 0을 리턴해주면 됩니다.
예를 들어, 문자열 S = baabaa 라면
b aa baa → bb aa → aa →
의 순서로 문자열을 모두 제거할 수 있으므로 1을 반환합니다.

제한사항
  - 문자열의 길이 : 1,000,000이하의 자연수
  - 문자열은 모두 소문자로 이루어져 있습니다.

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/12973

 

풀이보기
더보기
function solution(s) {
    let str = s.split('');
    
    while(str.length > 0) {
        let findStr = false;
        if(str.length % 2 !== 0) return 0;
        
        for(let i = 0; i < str.length; i++) {
            if(str[i] === str[i + 1]) {
                str.splice(i, 2);
                findStr = true;
                break;
                }
            }
        if(!findStr) return 0;
        }
    
    return 1;
}

 처음에 작성한 코드이다. 테스트 케이스는 다 통과했지만 효율성 테스트는 통과하지 못했다.

아무래도 s의 길이가 최대 1,000,000이기 때문에 효율적인 코드가 필요한 것 같다.

단순히 처음부터 배열을 순회하며 현재 인덱스와 다음 인덱스가 같은지 확인하고 같다면 splice로 삭제하게끔 했다.

또한 문자열 길이가 홀수이거나 findStr 변수로 연속된 문자가 없을 경우 0을 리턴하도록 해줬다.

마지막에 while 문을 빠져나온다면 str 길이가 0일테니 1을 리턴해줬다.

 

아무래도 splice는 제거할 때마다 배열을 재구성하기 때문에 비효율적인 것 같다.

그래서 찾은 방법은 스택이다!

function solution(s) {
    let stack = [];
    
    for (let i = 0; i < s.length; i++) {
        if (stack.length > 0 && stack[stack.length - 1] === s[i]) {
            stack.pop();
        } else {
            stack.push(s[i]);
        }
    }

    return stack.length === 0 ? 1 : 0;
}

스택은 후입선출의 특징을 가지고 있으며 문자열의 요소를 하나씩 넣으며 비교할 수 있다.

따라서 먼저 스택이 비어있는지 확인하고, 현재 문자와 스택의 마지막 문자가 같은지 확인한다.

조건을 충족하면 짝지어있는 문자임으로 삭제해주고, 아니라면 스택에 push 해준다.

 

문제에서 알려준 예시인 baabaa로 적용해보면,

1. 스택에 b가 추가된다. => stack = ['b']

2. 그다음 a에 대하여, 들어있는 b와 a는 같지 않으므로 그대로 a가 스택에 추가된다. => stack = ['b', 'a']

3. a와 앞선 a는 같으므로 삭제해준다. => stack = ['b']

4. b와 앞선 b는 같으므로 삭제한다. => stack = []

5. 현재 스택은 비어있으므로 그냥 a가 추가된다. => stack = ['a']

6. 마지막으로 현재 a와 앞선 a가 같으므로 삭제된다. => stack = []

7. 스택이 비어있으므로 1이 리턴된다.

 

스택을 활용하면 더 효율적으로 문제를 해결할 수 있다.

2단계로 넘어오면서 더 다양하게 문제를 풀어야하겠구나 싶었다 ㅠ

 

반응형
반응형
문제:
피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다.

예를들어
F(2) = F(0) + F(1) = 0 + 1 = 1
F(3) = F(1) + F(2) = 1 + 1 = 2
F(4) = F(2) + F(3) = 1 + 2 = 3
F(5) = F(3) + F(4) = 2 + 3 = 5
와 같이 이어집니다.

2 이상의 n이 입력되었을 때, n번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수, solution을 완성해 주세요.

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/12945

 

풀이보기

 

더보기
function solution(n) {
    let value = {};
    
    for(let i = 2; i <= n; i++) {
        value[0] = 0;
        value[1] = 1;
        value[i] = (value[i - 1] + value[i - 2]) % 1234567;
    }
    
    return value[n];
}

처음에는 객체를 사용해서 맵핑 시켜주는 방식을 선택했다.

근데 이렇게 연속되는 인덱스 값에서는 객체보다는 배열이 효율적이라고 해서 배열로 바꿔주었다.

 

function solution(n) {
    let value = [0, 1];
    
    for (let i = 2; i <= n; i++) {
        value[i] = (value[i - 1] + value[i - 2]) % 1234567;
    }
    
    return value[n];
}

주의할 점은 return 값에만 value[n] % 1234567을 해줬었는데 그러면 value[n]의 값이 너무 커져서 오버플로우가 발생한다.

따라서 값을 저장할 때부터 % 1234567을 해주면서 값이 커지는 것을 방지해줘야한다!

 

반응형
반응형
문제:
숫자로 이루어진 문자열 t와 p가 주어질 때, t에서 p와 길이가 같은 부분문자열 중에서,
이 부분문자열이 나타내는 수가 p가 나타내는 수보다 작거나 같은 것이 나오는 횟수를 return하는 함수 solution을 완성하세요.
예를 들어, t="3141592"이고 p="271" 인 경우, t의 길이가 3인 부분 문자열은 314, 141, 415, 159, 592입니다.
이 문자열이 나타내는 수 중 271보다 작거나 같은 수는 141, 159 2개 입니다.

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/147355?language=javascript

 

풀이보기
더보기

이 문제는 예전에 푼 기록이 있었는데, 그래도 다시 한 번 풀어보았다!

function solution(t, p) {
    let value = [];
    let count = 0;
    
    for(let i=0; i<t.length - p.length + 1; i++) {
        value.push(t.slice(i, i + p.length))
    }
    
    value.map((item) => {
        if(Number(item) <= Number(p)) {
            count += 1;
        }
    })
    
    return count;
}

이전에는 이렇게 풀었었다.

slice를 활용해서 부분 문자열들을 value에 담아놓고 그 이후 map을 이용해 value 값을 순회하며 count를 해줬다.

지금 보면 다시 리턴할 배열도 없는데 왜 map을 썼는지,

굳이 value를 다 담아놓고 난 후에 count를 해줄 필요가 있었는지 의문이 들었다.

그래서 다음과 같이 다시 풀어보았다.

 

function solution(t, p) {
    let count = 0;
    
    for(let i = 0; i < t.length - p.length + 1; i++) {
        let str = t.slice(i, i + p.length);
        if(Number(str) <= Number(p)) count++;
    }
    
    return count;
}

코드도 간결해지고 실행 속도도 빨라졌다.

달라진 점은, 반복문 안에서 바로 조건을 비교하여 count를 한 점이다.

이렇게 한다면 또 배열을 순회할 필요도 없고 바로바로 count하며 더 효율적인 코드가 되었다!

 

반응형
반응형
문제:
0과 1로 이루어진 어떤 문자열 x에 대한 이진 변환을 다음과 같이 정의합니다.
x의 모든 0을 제거합니다.x의 길이를 c라고 하면, x를 "c를 2진법으로 표현한 문자열"로 바꿉니다.
예를 들어, x = "0111010"이라면, x에 이진 변환을 가하면 x = "0111010" -> "1111" -> "100" 이 됩니다.
0과 1로 이루어진 문자열 s가 매개변수로 주어집니다.
s가 "1"이 될 때까지 계속해서 s에 이진 변환을 가했을 때, 이진 변환의 횟수와 변환 과정에서 제거된 모든 0의 개수를
각각 배열에 담아 return 하도록 solution 함수를 완성해주세요.

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/70129

 

풀이보기
더보기
function solution(s) {
    let count = 0;
    let zeroCount = 0;
    let arr = s.split('');
    let trans = '';
    let result = [];
    
    while(trans !== '1') {
        arr.forEach((el) => {
            if(el === '0') {
                zeroCount++;
            }
        })
        
        let filter = arr.filter(str => str !== '0');
        trans = filter.length.toString(2);
        count++;
        
        arr = trans.split('');
    }
    
    result.push(count, zeroCount);
    return result;
}

문제를 풀기 전 반복해야하는 순서를 정했다.

 

1. 0의 개수를 센다.

2. 0을 삭제한다.

3. 0을 삭제한 문자열의 길이를 2진수로 변환한다.

4. 변환한 횟수를 카운트한다.

5. s가 1인지 확인하고 아니면 다시 1번부터 반복한다.

 

이렇게 문제를 풀으려면 while문을 쓰는 것이 적합하다고 판단했다.

while문의 조건은 s가 1일 때까지 반복하도록 작성하고, forEach를 통해 0의 개수를 세어준다.

그 다음 filter 메서드를 활용하여 0을 제거한 배열을 반환해준다.

필터링한 배열의 길이를 통해 2진수 변환을 하고 trans에 저장해준다.

변환할 때마다 count를 더해주고, 여기서 주의할 점은 반복을 위해 trans를 다시 배열로 변환하여 arr에 저장해줘야한다.

그럼 s가 1이 될 때까지 해당 코드를 실행하고, 마지막에는 count(변환 횟수)와 zeorCount(0의 개수)를 리턴해주면 끝!

 

근데 보다보니 return 할 때 굳이 result를 선언하지 않아도 될 것 같다.

function solution(s) {
    let count = 0;
    let zeroCount = 0;
    let arr = s.split('');
    let trans = '';
    
    while(trans !== '1') {
        arr.forEach((el) => {
            if(el === '0') {
                zeroCount++;
            }
        })
        
        let filter = arr.filter(num => num !== '0');
        trans = filter.length.toString(2);
        count++;
        
        arr = trans.split('');
    }
    
    return [count, zeroCount];
}

 

반응형
반응형
문제:
정수를 저장한 배열, arr 에서 가장 작은 수를 제거한 배열을 리턴하는 함수, solution을 완성해주세요.
단, 리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴하세요.
예를들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴 하고, [10]면 [-1]을 리턴 합니다.

제한 조건
  - arr은 길이 1 이상인 배열입니다.
  - 인덱스 i, j에 대해 i ≠ j이면 arr[i] ≠ arr[j] 입니다.

입출력 예
  1) arr = [4,3,2,1], return = [4,3,2]
  2) arr = [10], return = [-1]

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/12935

 

풀이보기
더보기
function solution(arr) {
    let array = [...arr];
    let min = Math.min(...arr);
    
    if(array.length === 0) return [-1];
    
    for(let i = 0; i < array.length; i++) {
        if(array[i] === min) {
            array.splice(i, 1);
            return array;
        }
    }
}

정말 어이없는 문제였다 .. 분명 빈 배열과 10일 때 -1을 리턴하래서 그렇게 했었는데

알고보니 문제 오류였다 ㅎㅎ ;  그냥 빈 배열일 때만 -1을 리턴하면 된다.

이것 때문에 한참 시간을 버렸다 ㅎ;

 

일단 배열에서 최솟값을 찾아 저장해주고, 빈 배열을 먼저 확인하여 리턴해준다.

빈 배열이 아니라면 배열에서 최솟값과 같은 값을 찾고, splice 메서드를 통해 해당 인덱스를 삭제하고 리턴해주면 끝!

 

반응형
반응형
문제:
JadenCase란 모든 단어의 첫 문자가 대문자이고, 그 외의 알파벳은 소문자인 문자열입니다.
단, 첫 문자가 알파벳이 아닐 때에는 이어지는 알파벳은 소문자로 쓰면 됩니다.
문자열 s가 주어졌을 때, s를 JadenCase로 바꾼 문자열을 리턴하는 함수, solution을 완성해주세요.

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/12951

 

풀이보기
더보기
function solution(s) {
    let arrStr = s.split(' ');
     
    for(let i = 0; i < arrStr.length; i++) {
        arrStr[i] = arrStr[i].toLowerCase();
        arrStr[i] = arrStr[i].charAt(0).toUpperCase() + arrStr[i].slice(1);
    }
    
    return arrStr.join(' ');
}

일단 간편하게 수정하기 위해 공백을 기준으로 문자열을 배열로 변환해준다.

그런 후 반복문을 통해서 요구사항대로 수정해줄 예정이다.

 

제일 앞글자를 제외한 문자는 소문자이므로 먼저 소문자로 변환해준다.

그 후 문자열의 앞글자를 가져오는 charAt() 메서드를 이용해서 앞글자만 대문자로 변환해준다.

그리고 기존 앞글자는 삭제해준 뒤 둘이 붙여주면 된다.

마지막으로 join 메서드를 이용해서 문자열로 변환해주면 끝 !

 

처음에는 arrStr[i][0] = arrStr[i][0].toUpperCase();로 작성했었다. ㅎㅎ;

이게 안되는 이유가 문자열은 불변 객체이기 때문에 문자열의 특정 인덱스에 직접 값을 지정할 수 없다.

이제라도 알아서 다행이다 ㅎㅎ ..

 

반응형
반응형
문제:
길이가 같은 배열 A, B 두개가 있습니다. 각 배열은 자연수로 이루어져 있습니다.
배열 A, B에서 각각 한 개의 숫자를 뽑아 두 수를 곱합니다.
이러한 과정을 배열의 길이만큼 반복하며, 두 수를 곱한 값을 누적하여 더합니다.
이때 최종적으로 누적된 값이 최소가 되도록 만드는 것이 목표입니다.
(단, 각 배열에서 k번째 숫자를 뽑았다면 다음에 k번째 숫자는 다시 뽑을 수 없습니다.)

예를 들어 A = [1, 4, 2] , B = [5, 4, 4] 라면
A에서 첫번째 숫자인 1, B에서 첫번째 숫자인 5를 뽑아 곱하여 더합니다. (누적된 값 : 0 + 5(1x5) = 5)
A에서 두번째 숫자인 4, B에서 세번째 숫자인 4를 뽑아 곱하여 더합니다. (누적된 값 : 5 + 16(4x4) = 21)
A에서 세번째 숫자인 2, B에서 두번째 숫자인 4를 뽑아 곱하여 더합니다. (누적된 값 : 21 + 8(2x4) = 29)
즉, 이 경우가 최소가 되므로 29를 return 합니다.

배열 A, B가 주어질 때 최종적으로 누적된 최솟값을 return 하는 solution 함수를 완성해 주세요.

 

문제 풀어보기: https://school.programmers.co.kr/learn/courses/30/lessons/12941

 

풀이보기
더보기
function solution(A,B){
    let sum = 0;
    
    A.sort((a, b) => a - b);
    B.sort((a, b) => b - a);
    
    for(let i = 0; i < A.length; i++) {
        sum += A[i] * B[i];
    }
    
    return sum;
}

문제를 봤을 때, 최솟값을 구하려면 배열에서 가장 작은 수와 큰 수를 곱해주면 되지 않을까 하는 생각을 했다.

근데 그게 정답이었다 허허

일단 A, B를 각각 오름차순, 내림차순으로 정렬한 뒤 차례대로 곱해서 더해주면 끝!

 

근데 다른 사람 풀이를 보니, reduce를 활용하는걸 잊고 있었다.

reduce를 활용하면 가독성을 해치지 않는 선에서 더 간결한 코드 작성이 가능하다.

function solution(A,B){
    A.sort((a, b) => a - b);
    B.sort((a, b) => b - a);
   
    return A.reduce((total, val, i) => total + val * B[i], 0);
}

 

반응형

+ Recent posts