자바스크립트 기초 강의에서 배운 메소드들

  -  push(): 뒤에 삽입

  -  pop(): 뒤에 삭제

  -  unshift(): 앞에 삽입

  -  shift(): 앞에 삭제

 

 

arr.splice(n, m): n부터 m개의 요소를 지움

  -  삭제된 요소 반환

let arr = [1, 2, 3, 4, 5];
let result = arr.splice(1, 2);

console.log(arr); //[1, 4, 5]
console.log(result); //[2, 3]

 

 

arr.splice(n, m, x): n부터 m개의 요소를 지우고 x를 추가

let arr = [1, 2, 3, 4, 5];
arr.splice(1, 3, 100, 200);

console.log(arr); //[1, 100, 200, 5]

 

let arr = [1, 2, 3];
arr.splice(1, 0, 100, 200);

console.log(arr); //[1, 100, 200, 2, 3]

 

 

arr.slice(n, m): n부터 m-1까지 반환

  -  m을 생략하면 n부터 배열 끝까지 반환

  -  문자열에 파트에서 나온 slice와 같은 기능

let arr = [1, 2, 3, 4, 5];
arr.slice(1, 4); //[2, 3, 4];

let arr2 = arr.slice();
console.log(arr2); //[1, 2, 3, 4, 5] 출력

 

 

arr.concat(arr1, arr2, …): 합쳐서 새배열을 반환

let arr = [1, 2];

arr.concat( [3, 4] ); //[1, 2, 3, 4]

arr.concat( [3, 4], [5, 6] ); //[1, 2, 3, 4, 5, 6]

arr.concat( [3, 4], 5, 6 ); //[1, 2, 3, 4, 5, 6]

 

 

 

자바스크립트 기초 강의에서 배열의 반복은 for문이나 for…of를 사용

 

arr.forEach(func): 배열 반복, 함수를 인수로 받음

let users = [‘Baby’, ‘Angel’, ‘Noonsong’];

users.forEach((item, index, arr) => {
	console.log(`${index+1}. ${item}`); 
})


//	1. Baby
//	2. Angel
//	3. Noonsong

  →  item은 해당 요소 (Baby, Angel, Noonsong)

  →  index는 배열의 인덱스 (0, 1, 2)

  →  arr은 해당 배열 자체 (users)

  →  보통 첫번째와 두번째 인수만 사용, 세번째 인수 생략 가능

 

 

arr.indexOf(item, n): 배열의 인덱스 n부터 탐색을 시작, 진행 방향 →

arr. lastIndexOf (item, n): 배열 끝을 0으로 하여 n부터 탐색을 시작, 진행 방향 ←

  -  찾아낸 itemindex 반환, 없으면 -1 반환

  -  n이 생략되면 indexOf는 처음부터 탐색 시작, lastIndexOf는 끝에서부터 탐색 시작

 

ex)

let arr = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘a’, ‘b’, ‘c’];          

arr.indexOf(‘c’); //2
// → c의 위치는 index 2

arr.indexOf(‘c’, 3); //7
// → n>=3에서부터 탐색한 c의 위치는 index 7

arr.indexOf(‘c’, -4) //7
// → n>=-4에서부터 탐색한 c의 위치는 index 7



arr.lastIndexOf(‘c’); //7
//뒤에서부터 탐색한 c의 위치는 index 7

arr.lastIndexOf(‘c’, 6); //-1
// → n>=6에서부터 탐색한 c은 존재하지 않음, -1 반환

arr.indexOf(‘c’, -4) //2
// → n<=-4에서부터 탐색한 c의 위치는 index 2

 

 

arr.includes(item, n): 배열의 인덱스 n부터 탐색을 시작해서 item을 포함하는지 확인

  -  item을 포함하면 true, 그렇지 않으면 false 반환

  -  n을 생략하면 처음부터 탐색 시작

  -  n이 음수면 배열의 끝을 -1로 시작하여 배열 탐색

let arr = [1, 2, 3, 4, 5];

arr.includes(2); //true

arr.includes(8); //false

arr.includes(4, -3); //false

 

 

arr.find(func)

  -  첫번째 true인 값만 반환하고 끝, 없으면 undefined를 반환

let arr = [1, 2, 3, 4, 5];

const result = arr.find((item) => {
	return item % 2 === 0; //item이 짝수일 때 true
});

console.log(result); //2 출력

 

 

arr.findIndex(func)

  -  indexOf과 동일한 기능을 하지만 함수를 연결하여 좀 더 복잡한 연산이 가능

  -  첫번째 trueindex 값만 반환하고 끝, 없으면 -1을 반환

let userList  = [
	{ name: ‘Baby’, age: 10 },
	{ name: ‘Angel’, age: 27 },
	{ name: ‘Noonsong’, age: 30 }
];

const result = userList.find((user) => {
	if(user.age > 19) { return true; }
	return false;
});

console.log(result); // {name: “Angel”, age: 27} 출력

 
const index = userList.findIndex((user) => {
	if(user.age > 29) { return true; }
	return false;
});

console.log(index); // 2 출력

   

 

arr.filter(func): 만족하는 모든 요소를 배열로 반환

let arr = [1, 2, 3, 4, 5];

const result = arr.filter((item) => {
	return item % 2 === 0;
});

console.log(result); //[2, 4, 6] 출력

 

 

arr.reverse(): 배열을 역순으로 재정렬

let arr = [1, 2, 3, 4, 5];

arr.reverse(); //[5, 4, 3, 2, 1]

 

 

arr.map(func): 함수를 받아 특정 기능을 수행하고, 새로운 배열을 반환

let userList = [
	{ name: ‘Baby’, age: 10 },
	{ name: ‘Angel’, age: 27 },
	{ name: ‘Noonsong’, age: 30 }
];

const newUserList= userList.map((user, index) => {
	return Object.assign({}, user, {
		isAdult: user.age > 19
	});
});

console.log(newUserList); 


//	[ 
//		{name: “Baby”, age: 10, isAdult: false},
//		{name: “Angel”, age: 27, isAdult: true},
//		{name: “Noonsong”, age: 30, isAdult: true} 
//	]

  →  userList는 변경되지 않고 그대로

 

 

arr.join(): 배열의 모든 요소를 합해서 하나의 문자열로 반환

let arr = ["My", "name", "is", "Angel."];

console.log(arr.join()); //My, name, is, Angel. 출력

console.log(arr.join('')); //MynameisAngel. 출력

console.log(arr.join(' ')); //My name is Angel. 출력

console.log(arr.join('-')); //My-name-is-Angel. 출력

 

 

str.split(): 문자열을 지정한 구분자를 이용하여 여러 개의 문자열 배열로 반환

let str = "My name is Angel.";         

const words = str.split(' ');
console.log(words); //["My", "name", "is", "Angel."]

const chars = str.split('');
console.log(chars); //["M", "y", " ", "n", "a", "m", "e", " ", "I", "s", " ", "A", "n", "g", "e", "l", "."]

const strCopy = str.split();
console.log(strCopy); //["My name is Angel."]

 

 

Array.isArray(): 전달받은 인자가 배열인지 아닌지 판별, 배열이면 true 아니면 false 반환

let user = {
	name: 'Angel',
	age: 30,
};
 
let userList = ["Baby", "Angel", "Noonsong"];

console.log(typeof user); //object
console.log(typeof userList); //object

console.log(Array.isArray(user)); //false
console.log(Array.isArray(userList)); //true

      

 

 

 

↓[코딩앙마] 자바스크립트 중급 강좌 링크

https://www.youtube.com/watch?v=pJzO6O-aWew 

 

 

 

Fibonacci Sequence - Anatomy of recursion and space complexity analysis

 

Let's try to analyze the space complexity of recursive implementation of Fibonacci sequence.

To understand and analyze the memory consumption, we need to understand how recursive program executes in the memory.

 

 

On the right, it is computers memory and these partitions in the memory are basically some units in which the memory is divided.

 

When a method is executing, it is currently in the memory.

So, all the local variables and the information about the method is already in the memory.

 

 

When this main method makes a call to another method F(5), computer saves the current state of execution of this particular method. It pauses main method and go ahead to calculate F(5).

Now, F(5) is executing and then F(5) makes a call to F(4), which is recursive call.

Next, F(4) is executing and the computer has saved the state of F(5) as well.

Keep going on until F(1), and F(1) will not make any further function call, or recursive call, but simply return 1.

 

 

Now, F(1) has finished and it also gets popped from the memory and computer goes back to F(2).

F(2) at this stage makes another call to F(0), which simply returns 0 and finishes.

F(2) adds up these two values 1 and 0 and returns the sum 2 to F(3).

 

When F(5) sums up the two values, it returns to the main method which is its caller.

 

 

Now, the space consumed by this particular recursion was the memory that it consumed in the function call stack and the maximum growth of this call stack due to this particular recursion was when we were at the bottom-most node.

When F(1) was executing then all these states of F(5), F(4), F(3), F(2) were saved in the memory.

5 units of space were consumed in the memory and the call stack did not grow any larger than this.

The maximum space consumed by a recursive program is propotional to the maximum depth of this recursion tree. 

And the maximum depth of recursion tree is defined as the length of the longest path in the tree.

 

 

So if F(5) is Level0 in the tree and go down by one arrow, then F(4) is Level1, F(3) is Level2, F(2) is Level3, finally F(1) is Level4. 

The maximum depth in this case is the path from Level0 to Level4, which is 4 units, and the number of function calls is 5 so the maximum memory consumed is 5 units.

 

If we would have called the function Fib(n) then the maximum depth of the recursion tree would have been n-1 units, and the maximum space taken would have been n units.

 

In this case space or memory consumption is proportional to n and we can also say that this is O(n) in terms of space complexity.

 

 

 

 

↓ 참고 사이트

https://www.youtube.com/watch?v=dxyYP3BSdcQ&list=PL2_aWCzGMAwLz3g66WrxFGSXvSsvyfzCO&index=6 

 

 

 

Recursion with memorization technique to improve the performance of a recursive program

 

 

To avoid the recalculation of the same state or the same value, modify the function Fib(n) on the left.

 

When F(2) is calculated for the first time, save it in the memory so that it doesn’t have to be re-calculated.

And also any F(n), like F(3), F(4), and so on.

 

So if F(n) is in the memory, it doesn’t try to calculate, but simply return F(n).

Else, it tries to calculate F(n) by making recursive calls to calculate Fib(n-1) + Fib(n-2).

And save this F(n) in memory so that it doesn’t have to be re-calculated again.

 

 

Now we can see the recursion tree with improvement.

When F(3) is being calculated, F(1) doesn’t have to be calculated again because it is already in the memory so simply returns the value.

It is same for F(4) and F(5) because F(2) and F(3) is already in the memory.

 

This implementation reduces the time complexity of this particular program.

 

 

previous code for Fibonacci

#include<iostream>
using namespace std;

int Fib(int n) {
    if(n <= 1) {
    	return n;
    }
    return Fib(n-1) + F(n-2);
}

int main() {
    int n;
    cout<<"Give me an n: ";
    cin>>n;
    int result = Fib(n);
    cout<<result;
}

 

improved code for Fibonacci

#include<iostream>
using namespace std;

int F[51];

int Fib(int n) {
    if(n <= 1) {
    	return n;
    }
    if(F[n] != -1) {
    	return F[n];
    }
    F[n] = Fib(n-1) + F(n-2);
    return F[n];
}

int main() {
    for(int i=0; i<51; i++) {
    	F[i] = -1;
    }
    F[0]=0; F[1]=1;
    int n;
    cout<<"Give me an n: ";
    cin>>n;
    int result = Fib(n);
    cout<<result;
}

 

 

So the recursion with memoization in this particular example is not as efficient as an iterative implementation in terms of memory, but it is as good as an iterative implementation in terms of time.

 

 

 

 

↓ 참고 사이트

https://www.youtube.com/watch?v=UxICsjrdlJA&list=PL2_aWCzGMAwLz3g66WrxFGSXvSsvyfzCO&index=5 

 

 

+ Recent posts