137. 只出现一次的数字 II

  1. class Solution {
  2. public int singleNumber(int[] nums) {
  3. int once=0,twice=0;
  4. for(int num:nums){
  5. once=(once^num)&~twice;
  6. twice=(twice^num)&~once;
  7. }
  8. return once;
  9. }
  10. }

260. 只出现一次的数字 III

只有两个数字a、b出现了一次,其他数字都出现了两次。全部数字异或的结果就等于a^b。
假设a异或b的结果xor,最右第五位1。
说明a、b的第五位一个是0一个是1,把数组中最右第五位是0的数全部异或一遍,就可以找到那个单独的第五位是0的数字。
同样,把数组中最右第五位是1的数全部异或一遍,就可以找到那个单独的第五位是1的数字。

  1. class Solution {
  2. public int[] singleNumber(int[] nums) {
  3. int xor=0;
  4. for(int num:nums){
  5. xor=xor^num;
  6. }
  7. int flag=1;
  8. while((xor&1)==0){
  9. xor=xor>>1;
  10. flag=flag<<1;
  11. }
  12. int a=0,b=0;
  13. for(int num:nums){
  14. if((flag&num)==0){
  15. a=a^num;
  16. }else{
  17. b=b^num;
  18. }
  19. }
  20. return new int[]{a,b};
  21. }
  22. }

89. 格雷编码

  1. class Solution {
  2. public List<Integer> grayCode(int n) {
  3. /**
  4. 关键是搞清楚格雷编码的生成过程, G(i) = i ^ (i/2);
  5. 如 n = 3:
  6. G(0) = 000,
  7. G(1) = 1 ^ 0 = 001 ^ 000 = 001
  8. G(2) = 2 ^ 1 = 010 ^ 001 = 011
  9. G(3) = 3 ^ 1 = 011 ^ 001 = 010
  10. G(4) = 4 ^ 2 = 100 ^ 010 = 110
  11. G(5) = 5 ^ 2 = 101 ^ 010 = 111
  12. G(6) = 6 ^ 3 = 110 ^ 011 = 101
  13. G(7) = 7 ^ 3 = 111 ^ 011 = 100
  14. **/
  15. List<Integer> res = new ArrayList<>();
  16. for(int i=0;i<(1<<n);i++){
  17. res.add(i^(i>>1));
  18. }
  19. return res;
  20. }
  21. }

也可以用dfs,但是应该不是题目的本意?
因为这样才打败了10%

  1. class Solution {
  2. List<Integer> res = new ArrayList();
  3. boolean[] visited;
  4. public List<Integer> grayCode(int n) {
  5. visited = new boolean[1<<n];
  6. dfs(0,n);
  7. return res;
  8. }
  9. void dfs(int cur,int n){
  10. if(res.size()==(1<<n))
  11. return;
  12. res.add(cur);
  13. visited[cur]=true;
  14. for(int i=0;i<n;i++){
  15. int next = cur^(1<<i); //这里改变cur的某一位,用异或
  16. if(!visited[next]) dfs(next,n);
  17. }
  18. }
  19. }

338. 比特位计数

要多写几位找规律。
比如:
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111
16 10000
如果i是奇数,就只比上一个数多了一个末尾的1
如果i是偶数,就是把(从右往左数)1-n位的连续1变成n+1位的1

  1. class Solution {
  2. public int[] countBits(int num) {
  3. int[] dp=new int[num+1];
  4. if(num==0) return dp;
  5. for(int i=1;i<=num;i++){
  6. if(((i-1)&1)==0){
  7. dp[i]=dp[i-1]+1;
  8. }
  9. else{
  10. dp[i]=dp[i-1]-countOne(i-1)+1;
  11. }
  12. }
  13. return dp;
  14. }
  15. private int countOne(int n){
  16. int count=0;
  17. while((n&1)==1){
  18. n=n>>1;
  19. count++;
  20. }
  21. return count;
  22. }
  23. }