이 기사에서 우리는 k번째 비트 세트가 있는 주어진 범위에 존재하는 요소의 수를 찾는 문제에 대해 논의할 것입니다. 예를 들어 -
입력 :arr[] ={ 4, 5, 7, 2 }질의 1:L =2, R =4, K =4질의 2:L =3, R =5, K =1출력 :0 1사전>우리는 무차별 대입 접근 방식으로 이 문제를 해결하고 이 접근 방식이 더 높은 제약 조건에서 작동할 수 있는지 여부를 확인할 것입니다. 그렇지 않다면 새로운 효율적인 접근 방식을 생각하려고 합니다.
무차별 대입 접근
이 접근 방식에서는 단순히 범위를 살펴보고 k번째 비트가 설정되었는지 여부를 각 요소에 대해 확인하고, 설정되어 있으면 개수를 늘립니다.
예
#includeusing namespace std;#define MAX_BITS 32bool Kset(int n, int k) { // k번째 비트가 설정되었는지 확인하기 위해 if (n &(1 <<(k - 1) ))) true를 반환합니다. return false;}int query(int L, int R, int K, int arr[]) { int count =0; // 범위에 존재하는 숫자의 개수를 유지하기 위한 카운터 for (int i =L; i <=R; i++) { // 범위 순회 if (Kset(arr[i], K)) { count++; } } 반환 횟수;}int main() { int arr[] ={ 4, 5, 7, 2 }; // 주어진 배열 int n =sizeof(arr) / sizeof(arr[0]); // 배열의 크기 int query[][3] ={ // 주어진 L, R 및 k { 2, 4, 4 }, { 3, 5, 1 } }; 정수 q =sizeof(쿼리) / sizeof(쿼리[0]); // 쿼리 수 for (int i =0; i 출력
01위의 접근 방식은 O(N*Q)의 시간 복잡도를 가지고 있습니다. 여기서 N은 배열의 크기이고 Q는 현재 제공된 쿼리 수입니다. 보시다시피 이 접근 방식은 시간이 너무 오래 걸리므로 더 높은 제약 조건에는 적합하지 않으므로 이제 효율적인 접근 방식의 프로그램을 만들려고 합니다.
효율적인 접근
이 접근 방식에서는 각 인덱스까지 사용된 모든 비트의 수를 유지하는 2차원 접두사 합계 배열을 유지하고 O(1) 복잡도에서 답을 계산할 수 있습니다.
예
#include네임스페이스 사용 std;#define bits 32 // 비트 수int P[100000][bits+1];bool Kset(int n, int k) { if (n &( 1 <<(k - 1))) true를 반환합니다. return false;}void prefixArray(int n, int arr[]) { // (int i =0; i <=bits; i++) { P[0][i] =0; // 모든 비트 설정 초기 카운트 =0 } for (int i =0; i 출력
23O(1)에서 답을 찾는 데 도움이 되는 접두사 배열을 유지 관리하므로 시간 복잡도가 O(N)으로 크게 감소합니다. 여기서 N은 주어진 배열의 크기입니다.
위 코드 설명
이 프로그램에서 인덱스까지 사용된 모든 비트를 계산하는 배열의 모든 인덱스에 대한 접두사 카운터를 유지합니다. 모든 비트의 접두사 카운트가 저장되어 있으므로 배열에 대해 이 카운트를 작성합니다. 따라서 k번째 비트 카운트의 경우 k번째 비트의 접두사 카운트를 R 인덱스까지 빼야 합니다. 1개의 색인과 그것이 우리의 답입니다.
결론
이 글에서는 K번째 Bit Set을 사용하여 범위 내의 배열 요소 수에 대한 쿼리를 해결하는 문제를 해결합니다. 우리는 또한 이 문제에 대한 C++ 프로그램과 이 문제를 해결한 완전한 접근 방식( Normal 및 Efficient)을 배웠습니다. C, Java, python 및 기타 언어와 같은 다른 언어로 동일한 프로그램을 작성할 수 있습니다. 이 기사가 도움이 되기를 바랍니다.