异或问题(java)

1、题目:

题目描述

给定整数m以及n各数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个。

输入描述:

第一行包含两个整数n,m. 

第二行给出n个整数A1,A2,...,An。

数据范围

对于30%的数据,1 <= n, m <= 1000

对于100%的数据,1 <= n, m, Ai <= 10^5

输出描述:

输出仅包括一行,即所求的答案
示例1

输入

3 10  
6 5 10

输出

2



2、思想:

首先想到的是暴力法破解,但是看到给的的测试数据范围就知道会超时,但是还是先写了这个算法,就想知道通过率可以有多少;然后看了字典树方法,也基本学会了,虽然还是不够熟练,然而因为字典树核心思想是空间换时间,所以又超内存了...呃,目前想不出方法了,昨天晚上就看,今天还是没做出来,就先这样吧,等后期第二波刷题时候,看看左神的书也许会有新变化。



3、code:两个都没有a过,暴力法超时,通过率50%;字典树法超内存,通过率70%

(1)暴力法:

package schooloffer17;

import java.util.Scanner;

/**
 * @Author: cxh
 * @CreateTime: 17/11/20 15:54
 * @ProjectName: JavaBaseTest
 * <异或>
 */
public class XOR {
    public static void main(String[] args) {
        int n,m;
        Scanner scanner=new Scanner(System.in);
        while (scanner.hasNext()){
            n=scanner.nextInt();
            m=scanner.nextInt();
            int[] number=new int[n];
            for(int i=0;im?1:0;
                }
            }
            System.out.println(res);
        }
    }
}


(2)字典树法:

package schooloffer17;

import java.util.Scanner;

/**
 * @Author: cxh
 * @CreateTime: 17/11/20 15:54
 * @ProjectName: JavaBaseTest
 * <异或>
 * 关键算法:字典树TrieTree的应用
 */
public class XOR {
    private static class TrieTree{
        TrieTree[] next=new TrieTree[2];//next[0]表示左节点, next[1]表示右节点.
        int count=1;//表示有多少个数的在形成01字符串表达式的过程中,经过了这个节点
    }
    public static void main(String[] args) {
        int n,m;
        Scanner scanner=new Scanner(System.in);
        while (scanner.hasNext()){
            n=scanner.nextInt();
            m=scanner.nextInt();
            int[] number=new int[n];
            for(int i=0;i=0;j--){
                int digit=(a[i]>>j) & 1;
                if(curr.next[digit]==null){
                    curr.next[digit]=new TrieTree();//count=1是初始值,故这里就不用再new之后为count赋值为1了
                }else{
                    curr.next[digit].count++;
                }
                curr=curr.next[digit];
            }
        }
        return root;
    }

    /**
     * 搜索查找字典树
     * @param root 字典树根
     * @param a 要比较的元素
     * @param m 输入的比较值
     * @param move 需要右移的位数
     * @return
     */
    private static int searchTrieTree(TrieTree root,int a,int m,int move){
        if(root==null)
            return 0;

        TrieTree curr=root;
        for(int i=move;i>=0;i--){
            int aDigit=(a>>i) & 1;
            int mDigit=(m>>i) & 1;
            if(aDigit==0 && mDigit==0){
                int x=searchTrieTree(curr.next[0],a,m,i-1);
                int y=curr.next[1]==null?0:curr.next[1].count;
                return x+y;
            }else if(aDigit==0 && mDigit==1){
                if(curr.next[1]==null)
                    return 0;
                curr=curr.next[1];
            }else if(aDigit==1 && mDigit==0){
                int x=curr.next[0]==null?0:curr.next[0].count;
                int y=searchTrieTree(curr.next[1],a,m,i-1);
                return x+y;
            }else{
                if(curr.next[0]==null)
                    return 0;
                curr=curr.next[0];
            }
        }
        return 0;
    }
}



你可能感兴趣的:(算法,nowcoder笔记)