백준을 업로드하다 좀 뜸했는데, 그동안 공부 방법에 회의?를 느껴서 더 기초로 내려가고, 참고하는 자료도 기본 3개는 깔았다.
리트코드로 이진 탐색 스터디 플랜을 하고 있다.
무조건 easy 난이도부터 풀기 시작했는데, 가장 첫번째 기본 예제는 그냥 영상이랑 그림 보면서 코드 따라치면서 습관이 될 때까지 외웠다.
항상 성능을 최고로 내지는 못하는 수준이어서, 일단 Accepted를 목표로 했다.
브루트 포스 탐색은 말 그대로 무지성으로 하나하나 찾는 방식이다.
그것보다 효율적이기 위해서 start, mid, end를 사용한 이진탐색을 한다.
class Solution {
public int[] searchRange(int[] nums, int target) {
int x = target;
int n = nums.length;
int first = -1;
int last = -1;
for(int i = 0; i < n; i++) {
if(x != nums[i]) {
continue;
}
if(first == -1) {
first = i;
}
last = i;
}
if(first != -1) {
return new int[]{first, last};
} else {
return new int[]{-1, -1};
}
}
}
https://www.geeksforgeeks.org/find-first-and-last-positions-of-an-element-in-a-sorted-array/
사이트의 solutions 탭에 잘 나와있기도 한데 구글링한 이게 가장 짧아서 가져옴. 이건 근데 브루트 포스 탐색인데 통과한 것이 신기하다...
그냥 순차 탐색을 한 것 뿐인데...
난 이진 탐색 기본 예제로 풀었다가 time limit 탈락했다.
근본인 mid 구하는 방식을 다시 찾아봤다.
class Solution {
public int[] searchRange(int[] nums, int target) {
int first = findFirst(nums, target);
int last = findLast(nums, target);
return new int[]{first, last};
}
private int findFirst(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int first = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
if (mid == 0 || nums[mid - 1] != target) {
first = mid;
break;
} else {
right = mid - 1;
}
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return first;
}
private int findLast(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int last = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
if (mid == nums.length - 1 || nums[mid + 1] != target) {
last = mid;
break;
} else {
left = mid + 1;
}
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return last;
}
}