Find K Closest Elements K 최근 원소 발견

3186 단어 알고리즘
질서 있 는 배열 을 지정 하고 두 개의 정수 k 와 x 를 지정 하여 배열 에서 x 에 가장 가 까 운 요 소 를 찾 습 니 다.결과 도 오름차 순 으로 정렬 해 야 한다.무승부 가 있 으 면, 작은 요 소 는 항상 최 우선 입 니 다.
예 1: 입력: [1, 2, 3, 4, 5], k = 4, x = 3 출력: [1, 2, 3, 4] 예 2: 입력: [1, 2, 3, 4, 5], k = 4, x = - 1 출력: [1, 2, 3, 4] 주의: 값 k 는 정수 이 고 정렬 배열 의 길이 보다 항상 작 습 니 다.주어진 배열 의 길 이 는 양수 이 며 104 배열 과 x 에서 요소 의 절대 치 는 104 를 초과 하지 않 습 니 다.
사고 1: 2 분 을 통 해 찾 은 변종 해법 을 통 해 먼저 첫 번 째 x 와 같은 숫자 를 찾 은 다음 에 좌우 로 누가 x 와 가 까 운 지 비교 한 다음 에 해당 하 는 아래 표 시 를 순서대로 되 돌려 서 res 에 k 개의 숫자 가 있 을 때 까지 좌우 로 연장 합 니 다.
참조 코드:
    vector findClosestElements(vector& arr, int k, int x) {
	vector res;
	if (arr[0] >=x ) {
		for (int i = 0; i < k; i++) {
			res.push_back(arr[i]);
		}
		return res;
	}
	if (arr[arr.size()-1] <= x) {
		for (int i = (arr.size() - k); i < arr.size(); i++) {
			res.push_back(arr[i]);
		}
		return res;
	}
	int left = 0;
	int right = arr.size() - 1;
	while (left < right) {
		int mid = left + (right - left) / 2;
		if (arr[mid] < x) {
			left = mid + 1;
		}
		else {
			right = mid;
		}
	}
	int slow = left-1;
	int fast = left;
	while (res.size() != k && slow>=0 && fast abs(arr[fast] - x)) {
			res.push_back(arr[fast]);
			fast++;
		}
		else {
            if(slow==fast){
                			res.push_back(arr[slow]);
			slow--;
            fast++;
            }
            else{
                			res.push_back(arr[slow]);
			slow--;                
            }

		}
	}
	if (res.size() == k) {
		sort(res.begin(), res.end());
		return res;
	}
	while (res.size() != k) {
		if (slow >= 0) {
			res.push_back(arr[slow]);
			slow--;
		}
		else {
			res.push_back(arr[fast]);
			fast++;
		}
	}
	sort(res.begin(), res.end());
	return res;        
    }

사고 2: 이분법 이기 도 합 니 다. 필요 한 k 개의 숫자의 가장 왼쪽 아래 표 시 를 직접 되 돌려 줄 수 있 습 니 다. 먼저 left = 0, right = arr. size () - k 를 초기 화 할 수 있 습 니 다. 2 분 과정 에서 경 계 를 넘 지 않도록 보장 합 니 다. 매번 에 arr [mid] 와 arr [mid + k] 중 어느 것 이 x 와 가 까 운 지 비교 할 수 있 습 니 다. 만약 에 arr [mid + k] 가 가깝다 면 다음 과 같은 변 함 없 는 제약 이 성립 되 는 것 을 의미
abs(arr[mid+k+d]-target)

즉, arr [mid + k] 를 기점 으로 오른쪽으로 k 개 수 를 세 는 것 은 arr [mid] 를 기점 으로 오른쪽으로 k 개 수 를 세 는 것 보다 target 에 더 가깝다.그래서 arr [mid] 를 기점 으로 하고 mid 보다 작은 부분 이 가장 좋 은 것 이 아니 기 때문에 mid 의 왼쪽 부분 (mid 포함), 즉 left = mid + 1 을 포기 합 니 다.동 리 는 다른 쪽 에 대해 서도 같은 사상 이 고 마지막 결론 은 right = mid 이다.이곳 은 순환 처리 에 주의해 야 한다.즉:
abs(arr[mid+k+d]-target)>=abs(arr[mid+d]-target)

여기에 반드시 같은 기 호 를 포함해 야 한다. 그렇지 않 으 면 다음 과 같은 입력 [1, 2, 3, 4, 5] k = 4, target = 3.마지막 으로 두 가지 조건 을 만족 시 키 는 결과 가 나 올 것 이다.
참조 코드 는 다음 과 같 습 니 다.
    vector findClosestElements(vector& arr, int k, int x) {
	int left = 0;
	int right = arr.size() - k;
	while (left < right) {
		int mid = left + (right - left) / 2;
		if (abs(arr[mid] - x) <= abs(arr[mid + k] - x)) {
			right = mid;
		}
		else {
			left = mid+1;
		}
	}
	return vector(arr.begin()+left, arr.begin() + left+k);
    }

좋은 웹페이지 즐겨찾기