데이터 구조와 알고리즘에서 가장 인기있는 질문 중 하나는 주로 전화 인터뷰에 관한 것입니다.
데이터 구조와 알고리즘에서 가장 인기있는 질문 중 하나는 주로 전화 인터뷰에 관한 것입니다.
답변:
부정 행위와 동시에 두 번의 패스를 수행함으로써. 그러나 나는 신병 모집 자들이 이것을 좋아할지 모르겠다.
좋은 트릭으로 하나의 링크 된 목록에서 수행 할 수 있습니다. 두 개의 포인터가 목록 위로 이동합니다. 하나는 배속입니다. 빠른 사람이 끝에 도달하면 다른 사람이 절반입니다.
이중 연결 목록이 아닌 경우 목록을 계산하고 사용할 수 있지만 최악의 경우에는 메모리를 두 배로 늘려야하며 목록이 너무 커서 메모리에 저장하기에는 작동하지 않습니다.
간단하고 거의 바보 같은 해결책은 두 노드마다 중간 노드를 늘리는 것입니다.
function middle(start) {
var middle = start
var nextnode = start
var do_increment = false;
while (nextnode.next != null) {
if (do_increment) {
middle = middle.next;
}
do_increment = !do_increment;
nextnode = nextnode.next;
}
return middle;
}
Hendrik의 답변 에 대해 자세히 설명
이중 연결 목록 인 경우 양쪽 끝에서 반복
function middle(start, end) {
do_advance_start = false;
while(start !== end && start && end) {
if (do_advance_start) {
start = start.next
}
else {
end = end.prev
}
do_advance_start = !do_advance_start
}
return (start === end) ? start : null;
}
주어진 [1, 2, 3] => 2
1, 3
1, 2
2, 2
주어진 [1, 2] => 1
1, 2
1, 1
주어진 [1] => 1
주어진 [] => null
배열의 각 요소가 처음부터 시작하여 순회 순서로 목록의 각 노드에 대한 포인터 인 동적 배열을 작성하십시오. 방문한 노드 수를 추적하는 1로 초기화 된 정수를 작성하십시오 (새 노드로 갈 때마다 증가 함). 끝에 도달하면 목록의 크기를 알 수 있으며 각 노드에 대한 포인터 배열이 정렬되어 있습니다. 마지막으로, 목록의 크기를 2로 나누고 (0 기반 색인의 경우 1을 빼기) 배열의 해당 색인에있는 포인터를 가져옵니다. 목록의 크기가 홀수 인 경우 반환 할 요소를 선택할 수 있습니다 (여전히 첫 번째 요소를 반환합니다).
여기에 요점을 얻는 Java 코드가 있습니다 (동적 배열의 아이디어는 약간 기발한 것임에도 불구하고). 나는 C / C ++를 제공 할 것이지만 그 지역에서는 매우 녹슬었다.
public Node getMiddleNode(List<Node> nodes){
int size = 1;
//add code to dynamically increase size if at capacity after adding
Node[] pointers = new Node[10];
for (int i = 0; i < nodes.size(); i++){
//remember to dynamically allocate more space if needed
pointers[i] = nodes.get(i);
size++;
}
return pointers[(size - 1)/2];
}
재귀는 하나 이상의 패스로 간주됩니까?
정수 카운트를 참조로 전달하여 목록을 끝까지 탐색하십시오. 나중에 참조 할 수 있도록 각 레벨에서 해당 값의 로컬 사본을 작성하고 다음 호출로가는 참조 횟수를 늘리십시오.
마지막 노드에서 카운트를 2로 나누고 결과를 잘라 내고 (두 요소 만있을 때 첫 번째 노드가 "중간"이되도록하려면) 반올림 (두 번째 노드를 원하는 경우) 중간"). 0 또는 1 기준 인덱스를 적절하게 사용하십시오.
풀기, 참조 카운트를 로컬 카피 (노드 번호)와 일치시킵니다. 같으면 해당 노드를 반환하십시오. 그렇지 않으면 재귀 호출에서 반환 된 노드를 반환합니다.
.
이를 수행하는 다른 방법이 있습니다. 그들 중 일부는 덜 성 가실 수 있습니다 (누군가 그것을 배열로 읽고 배열 길이를 사용하여 중간 정도를 결정한다고 말하는 것을 알았습니다). 그러나 솔직히 말해서 좋은 답변은 없습니다. 어리석은 인터뷰 질문이기 때문입니다. 여전히 연결 목록 ( 지지 의견 )을 사용하는 1 위; 둘째, 중간 노드를 찾는 것은 실제 시나리오에서 가치가없는 임의의 학문적 운동입니다. 셋째, 실제로 중간 노드를 알아야 할 경우 연결된 목록에 노드 수가 노출됩니다. 중간 노드를 원할 때마다 전체 목록을 순회하는 시간을 낭비하는 것보다 해당 속성을 유지 관리하는 것이 더 쉽습니다. 마지막으로 네 명, 모든 면접관은 다른 답변을 좋아하거나 거부 할 것입니다. 한 면접관이 매끄럽다 고 생각하는 사람은 말도 안됩니다.
나는 거의 항상 더 많은 질문으로 인터뷰 질문에 대답합니다. 이와 같은 질문을 받으면 (필자는 없음) (1)이 링크 된 목록에 무엇을 저장하고 있으며 실제로 필요한 경우 중간 노드에 효율적으로 액세스 할 수있는 더 적절한 구조가 있습니까? ; (2) 나의 제약은 무엇인가? 메모리가 문제가 아닌 경우 (예 : 배열 응답) 더 빨라질 수 있지만, 인터뷰 담당자가 메모리를 크게 늘리는 것이 낭비라고 생각하면 쇠약해질 것입니다. (3) 어떤 언어로 개발할 예정입니까? 내가 아는 거의 모든 현대 언어에는 목록을 탐색 할 필요가없는 링크 된 목록을 처리하기위한 내장 클래스가 있습니다. 왜 언어 개발자가 효율성을 위해 조정 한 것을 다시 발명해야합니까?
2 개의 포인터를 사용합니다. 반복 할 때마다 하나씩 증가시키고 매번 반복 할 때마다 하나씩 증가시킵니다. 첫 번째 포인터가 연결된 목록의 끝을 가리킬 때 두 번째 포인터는 연결된 목록의 중간 모드를 가리 킵니다.