[알고리즘 총화] 2 점 찾기
8485 단어 데이터 구조
2 점 찾기 는 쓰기 쉽 지만 쓰기 가 쉽 지 않 습 니 다. 통계 에 따 르 면 10% 의 프로그래머 만 bug 가 없 는 2 점 찾기 코드 를 쓸 수 있 습 니 다.오류 원인 은 판정 조건 과 경계 값 의 선택 에 집중 되 어 있 기 때문에 경 계 를 넘 거나 순환 하 는 상황 을 초래 하기 쉽다.
다음은 2 분 의 검색 과 변형 에 대해 정리 하 겠 습 니 다.
1. 가장 기본 적 인 2 점 찾기
public int binarySearch(int[] A, int target, int n){
int low = 0, high = n, mid;
while(low <= high){
mid = low + (high - low) / 2;
if(A[mid] == target){
return mid;
}else if(A[mid] > target){
high = mid - 1;
}else{
low = mid + 1;
}
}
return -1;
}
그 중 몇 가지 주의해 야 할 점 이 있다.
low <= high
mid = low + (high - low)/2
A[mid]
과 같 지 않 을 때 target
또는 high = mid - 1
2. 목표 값 영역의 왼쪽 경 계 를 찾 습 니 다. / 목표 값 과 같은 첫 번 째 위 치 를 찾 습 니 다. / 목표 값 보다 작 지 않 은 첫 번 째 위 치 를 찾 습 니 다.
A = [1,3,3,5, 7 ,7,7,7,8,14,14] target = 7 return 4
public int binarySearchLowerBound(int[] A, int target, int n){
int low = 0, high = n, mid;
while(low <= high){
mid = low + (high - low) / 2;
if(target <= A[mid]){
high = mid - 1;
}else{
low = mid + 1;
}
}
if(low < A.length && A[low] == target)
return low;
else
return -1;
}
3. 목표치 영역의 오른쪽 경 계 를 찾 습 니 다. / 목표치 와 같은 마지막 위 치 를 찾 습 니 다. / 목표치 보다 크 지 않 은 마지막 위 치 를 찾 습 니 다.
A = [1,3,3,5,7,7,7, 7 ,8,14,14] target = 7 return 7
public int binarySearchUpperBound(int[] A, int target, int n){
int low = 0, high = n, mid;
while(low <= high){
mid = low + (high - low) / 2;
if(target >= A[mid]){
low = mid + 1;
}else{
high = mid - 1;
}
}
if(high >= 0 && A[high] == target)
return high;
else
return -1;
}
이 문 제 는 변형 가능
low = mid + 1
으로 우 리 는 마지막 으로 목표치 보다 크 지 않 은 수 를 찾 았 다. 그러면 한 명 더 뒤로 들 어가 서 /
로 돌아 가 는 것 이 목표치 보다 큰 첫 번 째 수 이다.검 지 offer: 정렬 배열 에 숫자 가 나타 나 는 횟수
4. 마지막 으로 목표치 보다 작은 숫자 찾기 / 목표치 보다 작 지만 목표치 에 가장 가 까 운 숫자 찾기
이 문 제 는 두 번 째 문제 에서 변형 할 수 있 습 니 다. 우 리 는 목표 치 구역 의 아래 (왼쪽) 경 계 를 찾 았 습 니 다. 그러면 다시 한 번 왼쪽으로 물 러 나 는 것 이 목표 치 보다 작은 숫자 입 니 다.사실
high + 1
도 순환 종료 후 low - 1
의 값 이기 때문이다. low - 1
는 마침 high
과 같 고 high
보다 작 기 때문에 while 순환 이 끝났다.우 리 는 low - 1
국경 을 넘 었 는 지 판단 하기 만 하면 된다.A = [1,3,3, 5 ,7,7,7,7,8,14,14] target = 7 return 3
int low = 0, high = n, mid;
while(low <= high){
mid = low + (high - low) / 2;
if(target <= A[mid]){
high = mid - 1;
}else{
low = mid + 1;
}
}
return high < 0 ? -1 : high;
5. 목표치 보다 큰 첫 번 째 숫자 찾기 / 목표치 보다 크 지만 목표치 에 가장 가 까 운 숫자 찾기
이 문 제 는 세 번 째 문제 에서 변형 할 수 있 는 것 으로 우 리 는 목표 치 구역 의 상 (우) 경 계 를 찾 았 다. 그러면 다시 오른쪽으로 한 자리, 즉
low
가 목표 치 보다 큰 첫 번 째 숫자 이다.사실 high
도 순환 종료 후 high + 1
의 값 이기 때문이다. high + 1
는 마침 low
과 같 고 low
보다 크 기 때문에 while 순환 이 끝난다.우 리 는 high + 1
국경 을 넘 었 는 지 판단 하기 만 하면 된다.A = [1,3,3,5,7,7,7,7, 8 ,14,14] target = 7 return 8
int low = 0, high = n, mid;
while(low <= high){
mid = low + (high - low) / 2;
if(target >= A[mid]){
low = mid + 1;
}else{
high = mid - 1;
}
}
return low > n ? -1 : low;
6. 회전 배열 에서 최소 요 소 를 되 돌려 줍 니 다.
6.1 회전 배열 의 최소 요 소 를 찾 습 니 다 (중복 숫자 가 존재 하지 않 는 다 고 가정)
LeetCode: Find Minimum in Rotated Sorted Array Input: [3,4,5,1,2] Output: 1
public int findMin(int[] nums) {
int len = nums.length;
if(len == 0)
return -1;
int left = 0, right = len - 1, mid;
while(left < right){
mid = left + (right - left) / 2;
if(nums[mid] > nums[right])
left = mid + 1;
else{
right = mid;
}
}
return nums[left];
}
여기 와 이전의 2 분 에서 찾 은 몇 가지 차이 점 을 주의 하 세 요.
high
, 등호 low
에 앞부분 이 질서 가 있 고 최소 치가 후반 부분 에 있 음 을 나타 낸다. 령 left < right
;nums[mid] > nums[right]
에 최소 치가 앞부분 에 있다 는 것 을 의미한다.마지막 으로 left 는 최소 값 요소 가 있 는 위 치 를 가리킨다.
6.2 회전 배열 의 최소 요 소 를 찾 습 니 다 (중복 항목 이 존재 합 니 다)
LeetCode: Find Minimum in Rotated Sorted Array II 검 지 offer: 회전 배열 의 최소 숫자 입력: [2, 2, 2, 0, 1] 출력: 0
public int findMin(int[] nums) {
int len = nums.length;
if(len == 0)
return -1;
int left = 0, right = len - 1, mid;
while(left < right){
mid = left + (right - left) / 2;
if(nums[mid] > nums[right])
left = mid + 1;
else if(nums[mid] < nums[right])
right = mid;
else
right--;
}
return nums[left];
}
이전 과 중복 항목 이 존재 하지 않 는 차 이 는
left = mid + 1
일 때 최소 값 이 nums[mid] <= num[right]
왼쪽 이 든 오른쪽 이 든 우 리 는 오른쪽 경 계 를 1 로 줄 입 니 다.7. 회전 정렬 배열 에서 검색
7.1 중복 항목 을 고려 하지 않 음
LeetCode: Search in Rotated Sorted Array
법 1:
right = mid
으로 진실 한 mid 의 위 치 를 구한다.public int search(int[] nums, int target) {
int len = nums.length;
if(len == 0)
return -1;
int left = 0, right = len - 1, mid;
while(left < right){
mid = left + (right - left) / 2;
if(nums[mid] > nums[right])
left = mid + 1;
else
right = mid;
}
int offset = left;
left = 0;
right = len - 1;
while(left <= right){
mid = left + (right - left) / 2;
int realmid = (mid + offset) % len;
if(nums[realmid] == target)
return realmid;
else if(nums[realmid] < target)
left = mid + 1;
else
right = mid - 1;
}
return -1;
}
법 2: 사실 회전 배열 의 경계 점 을 찾 을 필요 가 없습니다. 왼쪽 이나 오른쪽 을 검색 할 때 저 희 는 mid 와 high 의 요소 크기 에 따라 판단 할 수 있 습 니 다. target 의 값 에 따라 2 분 검색 을 하면 됩 니 다.
public int search(int[] nums, int target) {
int len = nums.length;
if(len == 0)
return -1;
int left = 0, right = len - 1, mid;
while(left <= right){
mid = left + (right - left) / 2;
if(nums[mid] == target)
return mid;
else if(nums[left] <= nums[mid]){
if(target < nums[mid] && target >= nums[left])
right = mid - 1;
else
left = mid + 1;
}else if(nums[mid] <= nums[right]){
if(target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
}
return -1;
}
7.2 중복 항목 존재
LeetCode: Search in Rotated Sorted Array II
public boolean search(int[] nums, int target) {
int len = nums.length;
if(len == 0)
return false;
int left = 0, right = len - 1, mid;
while(left <= right){
mid = left + (right - left) / 2;
if(nums[mid] == target)
return true;
else if(nums[mid] > nums[right]){
if(target < nums[mid] && target >= nums[left])
right = mid;
else
left = mid + 1;
}else if(nums[mid] < nums[right]){
if(target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid;
}else{
right --;
}
}
return false;
}
8. 2 차원 배열 에서 찾기
검 지 offer: 2 차원 배열 에서 찾기
2 차원 배열 은 질서 가 있 고 오른쪽 상단 을 보면 왼쪽 숫자 로 점점 줄 어 들 고 아래 숫자 로 점점 증가한다.따라서 이분 으로 찾 을 수 있 는 사상 을 이용 하여 오른쪽 상단 에서 출발 할 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.