자바 소스 코드 Integer.bitCount 알고리즘 분석,분석 원리(통계 2 진 bit 비트)
일반 알고리즘
public int bitCount(int num) {
int count = 0;
do {
if ((num & 1) == 1) {
count++;
}
num>>=1;
} while (num > 0);
return count;
}
가장 먼저 떠 오 르 는 알고리즘 일 것 입 니 다.최 하위 부터 한 사람 한 사람 이 1 인지,시간 복잡 도 는
O(n)
이 고 n 은 총 bit 수 입 니 다.최적화 알고리즘
public int countBit2(int num) {
int count = 0;
while (num > 0) {
num = num & (num - 1);
count++;
}
return count;
}
이 알고리즘 은 얼핏 보면 어 리 석 지만 곰 곰 이 생각해 보면 원 리 를 발견 할 수 있다.
n-1
후 n 의 최 하위 1 이 제거 되 었 고 n 비트 와 n 이 최 하위 1 에서 0 으로 변 한 후의 새로운 정수 이다.예 를 들 어:0b101100 0b101011 1 ,0b101100 & 0b101011 = 0b101000
이렇게 몇 번 순환 하면 몇 개의 1 이 있 고 시간 복잡 도 역시
O(n)
이다.그러나 이 n 은 bit 비트 가 1 인 개 수 를 나타 내 고 전체적으로 이전 보다 좋 은 것 이다.우리 가 이것 이 이미 가장 좋 은 알고리즘 이 라 고 생각 했 을 때,사실은 그렇지 않 았 다.Integer.bitCount
public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}
마지막 으로 자바 의 Integer 류 는 bit 비트 비트(기호 없 이 오른쪽으로 이동 하면 음 수 를 통계 할 수 있 는)를 통계 하 는 방법 을 제공 했다.얼핏 보면 WTF?원리:1 열의 1 이 우리 의 머 릿 속 에 놓 여 있 을 때 우 리 는 어떻게 세 나 요?하나의 숫자,첫 번 째 산법 의 원리.아니면 두 개,두 개?이 방법 은 이렇게 실현 되 었 다.다음 그림:
1 0 1 1 1 1 1 1 1 1 10 11 11 11 11
01 10 10 10 10 1 2 2 2 2
\ / \ / \/ \/
01 0100 0100 1 4 4
\ / \ /
01 1000 1 8
\ / \ /
1001 9
767 1
각 두 비트 는 한 그룹 으로 각각 몇 개의 1 을 통계 한 다음 에 결 과 를 이 두 비트 에 저장 합 니 다.예 를 들 어
11
은 2 개의 1 이 있 고 결 과 는 10
이 며 10
을 대체 하여 원래 위치 에 저장 합 니 다.그리고 덧셈 을 해서 모든 결 과 를 더 해라.가 하 는 과정 에서 두 가 지 를 더 해 계산 절 차 를 줄 일 수 있다.두 bit 계산 1 의 수량:
11
,0b11: 0b01 + 0b01 = 0b10 = 2
,이렇게 하면 알 수 있다.알고리즘 구현 은 다음 과 같 습 니 다.
0b10: 0b01 + 0b00 = 0b01 = 1
을 더 했다.i & 0x55555555
은 왼쪽 을 오른쪽으로 옮 기 고 왼쪽 을 지우 면 두 비트 위의 1 의 개 수 를 계산 할 수 있다 고 말 했다.(i >>> 1) & 0x55555555
왼쪽 두 분 은 1 개,오른쪽 두 분 은 2 개 1 이 있다.0b1011=>0b0001 + 0b0101 = 0b0110
에 두 사람의 통계 결 과 를 저장 하여 두 사람 을 더 해서 마지막 으로 화 해 를 구 할 수 있다.프로 세 스:
0x55555555 0b01010101010101010101010101010101
0x33333333 0b00110011001100110011001100110011
0x0f0f0f0f 0b00001111000011110000111100001111
0x00ff00ff 0b00000000111111110000000011111111
0x0000ffff 0b00000000000000001111111111111111
0x3f 0b00111111
0b11 11 11 11 11 (i & 0x55555555) + ((i >>> 1) & 0x55555555) = 0b0101010101 + 0b0101010101 = 0b1010101010
0b10 10 10 10 10 (i & 0x33333333) + ((i >>> 2) & 0x33333333) = 0b1000100010 + 0b00100010 = 0b1001000100
0b10 01 00 01 00 (i & 0x0f0f0f0f) + ((i >>> 4) & 0x0f0f0f0f) = 0b1000000100 + 0b0100 = 0b1000001000
0b10 00 00 10 00 (i & 0x00ff00ff) + ((i >>> 8) & 0x00ff00ff) = 0b1000 + 0b10 = 0b1010
0b00 00 00 10 10 (i & 0x0000ffff) + ((i >>> 16) & 0x0000ffff) = 0b1010 + 0 = 0b1010
dec 10
알고리즘 원형:
public static int bitCount(int i) {
i = (i & 0x55555555) + ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i & 0x0f0f0f0f) + ((i >>> 4) & 0x0f0f0f0f);
i = (i & 0x00ff00ff) + ((i >>> 8) & 0x00ff00ff);
i = (i & 0x0000ffff) + ((i >>> 16) & 0x0000ffff);
return i;
}
시간 복잡 도 O(1),좋아,좋아!그러나 글 을 쓸 때 모두 윤색 해 야 한다.알고리즘 은 말 할 것 도 없고 최적화 한 후에 Integer 에서 의 실현 이다.최적화:
i
,0b11: 0b01 + 0b01 = 0b10 = 2
.연구 결과:0b10: 0b00 + 0b01 = 0b01 = 1
,2=0b11-0b1
,한 번 줄 일 수 있 는 계산:1=0b10-0b1
i = i - ((i >>> 1) & 0x55555555)
연산 을 한 번 줄 일 수 있 습 니 다.&
i = (i + (i >>> 4)) & 0x0f0f0f0f
7 0b111
i = 7 - ((7>>>1) & 0x55555555) = 6 = 0b110
i = (6 & 0x33333333) + ((6 >>> 2) & 0x33333333) = 2 + 1 = 3 = 0b11
i = (3 + (i >>> 4)) & 0x0f0f0f0f = 3 & 0x0f0f0f0f = 3 = 0b11
i = 3 + (3 >>> 8) = 3 = 0b11
i = 3 + (3 >>> 16) = 3 = 0b11
i = 3 & 0x3f = 3
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
프로그램 원숭이 의 낭만적 인 이 진 표백편그날 발 렌 타인 데 이에 나 는 그녀 에 게 숫자 (01001001 00100000 011011011011010 01101001 00100000 0111001001 011011011011011101) 를 보 냈 다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.