Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有有效时间复杂度的n个二进制回文_Java - Fatal编程技术网

Java 具有有效时间复杂度的n个二进制回文

Java 具有有效时间复杂度的n个二进制回文,java,Java,给定一个整数N,我试图找到第N个二进制回文。我已经写了下面的代码,但效率不高。在时间复杂度方面,有没有更有效的方法。 我在网上试着把它当作一个问题,我应该在1秒或更短的时间内输出,但每输入一次就需要2秒 public static Boolean Palind(String n){ String reverse = ""; int length = n.length(); for(int i = length - 1; i >=0;i--){ rev

给定一个整数N,我试图找到第N个二进制回文。我已经写了下面的代码,但效率不高。在时间复杂度方面,有没有更有效的方法。 我在网上试着把它当作一个问题,我应该在1秒或更短的时间内输出,但每输入一次就需要2秒

public static Boolean Palind(String n){
    String reverse = "";
    int length = n.length();
    for(int i = length - 1; i >=0;i--){
        reverse = reverse + n.charAt(i);
    }
    if(n.equals(reverse)){
        return true;
    }
    else{
        return false;
    }
}

public static int Magical(int n){
    ArrayList<Integer> res = new ArrayList<Integer>();
    for(int i = 1; i < Math.pow(2, n);i++){
        if(Palind(Integer.toBinaryString(i))){
            res.add(i);
        }
    }
    return res.get(n-1);
}
public静态布尔Palind(字符串n){
字符串反向=”;
int length=n.length();
对于(int i=length-1;i>=0;i--){
反向=反向+n.字符(i);
}
如果(n等于(反向)){
返回true;
}
否则{
返回false;
}
}
公共静态整数(整数n){
ArrayList res=新的ArrayList();
for(inti=1;i
优化的想法, 让我们看看回文序列0,1,11,101,111,1001等等

所有数字都必须以1开头和结尾,因此中间位只会发生变化,中间子字符串应该是回文的,整个字符串才能变为回文

    让我们取一个2位二进制数——一个回文是可能的。< /P> 十进制3的二进制是回文11

  • 对于3位二进制数,可能有2个回文,2*(1位回文的编号)

    十进制5的二进制是回文101

    十进制7的二进制是回文111

  • 对于5位二进制数4回文可能2*(3位回文的数量)

    1000110101、11011、11111

    等等,

所以是2+20+21+22++2i-N

我们解出i并找出回文数

所以通过分析这个序列,我们得到了一个方程,如2(i/2)+1-1=N

其中N是回文的编号

i是第n个回文字符串中的位数

使用这个我们可以找到字符串的长度,从这个我们可以很早找到字符串


这可能很复杂,但有助于快速求解更高的N值……

尝试类似的方法吗

public static void main(String[] args) {
    for (int i = 1; i < 65535; i++) {
        System.out.println(
                i + ": " + getBinaryPalindrom(i) + " = " + Integer.toBinaryString(getBinaryPalindrom(i)));
    }
}

public static int getBinaryPalindrom(int N) {
    if (N < 4) {
        switch (N) {
            case 1:
                return 0;
            case 2:
                return 1;
            case 3:
                return 3;
        }
        throw new IndexOutOfBoundsException("You need to supply N >= 1");
    }
    // second highest to keep the right length (highest is always 1)
    final int bitAfterHighest = (N >>> (Integer.SIZE - Integer.numberOfLeadingZeros(N) - 2)) & 1;
    // now remove the second highest bit to get the left half of our palindrom
    final int leftHalf = (((N >>> (Integer.SIZE - Integer.numberOfLeadingZeros(N) - 1)) & 1) << (Integer.SIZE -
            Integer.numberOfLeadingZeros(N) - 2)) | ((N << (Integer.numberOfLeadingZeros(N) + 2)) >>> (Integer.numberOfLeadingZeros(N) + 2));
    // right half is just the left reversed
    final int rightHalf = Integer.reverse(leftHalf);
    if (Integer.numberOfLeadingZeros(leftHalf) < Integer.SIZE / 2) {
        throw new IndexOutOfBoundsException("To big to fit N=" + N + " into an int");
    }
    if (bitAfterHighest == 0) {
        // First uneven-length palindromes
        return (leftHalf << (Integer.SIZE - Integer.numberOfLeadingZeros(leftHalf)) - 1) | (rightHalf
                >>> Integer.numberOfTrailingZeros(rightHalf));
    } else {
        // Then even-length palindromes
        return (leftHalf << (Integer.SIZE - Integer.numberOfLeadingZeros(leftHalf))) | (rightHalf
                >>> Integer.numberOfTrailingZeros(rightHalf));
    }
}
如果你仔细阅读的话,有很多好的建议。例如,
a(2^n-1)=2^(2n-2)-1
可以让您快速跳转到第(2n-1)个回文

它还提供了几个实现。例如,Smalltalk实现是这样工作的(请注意,输入值
n
,第一个回文
0
1
开头):

public静态final int n布尔回文(int n){
如果(n==1)返回0;
如果(n==2)返回1;
int m=31-整数。前导零的个数(n);
整数c=1=3*c){
int a=n-3*c;
int d=2*c*c;
b=d+1;
int k2=1;
对于(int i=1;ik2我对@Kiran Kumar有同样的想法:你不应该一个接一个地数数数字,以确定它是否是一个速度太慢的二进制回文,而应该找到该数字的内部模式

逐个列出二进制字符串中的数字,您可以找到模式:

0
1
11
101
1001
1111
...
1......1
下面是一些数学问题: 我们有二进制格式的
2^取整((L-2)/2)
长度为
L
的数字回文。 对每个较短长度的数字求和,我们得到以下
len
Sum
映射:

for (int i = 1; i < mapping.length; i++) {
    mapping[i] = (long) (mapping[i - 1] + Math.pow(2, Math.ceil((i - 1) * 1.0 / 2)));
}

可以在中找到带有测试的完整代码,以生成大可能
long

可能不是-问题是关于性能的,并且完全在这里讨论。为什么需要将所有回文存储在数组中?使一些
int count=0
。每次找到回文时,将其递增,返回当前回文de>如果count==n
。然后进行一点优化,您不需要检查整数是否等于倒数。您只需要检查数字的前半部分是否等于倒数第二部分。您好@Ujjawal Malik我需要相同的解决方案请帮助将0和1视为回文?为什么不?这很简单,但仍然有效。这不是Smalltalk。对,原来是Smalltalk(参见OEIS链接中的Smalltalk代码)我把它翻译成Java来回答如何用Java实现的问题。我在你提到的git repo上找不到完整的代码。你能更新你的代码吗?因为我非常需要它。这意味着什么elaborate@R.S.如果n是1*1*00101,我将使用第二高的位来决定下一个回文是否为偶数或者长度不均匀。然后我删除留下的位,例如100101,并构建最终回文。使用第二高的位确保所有低位都可以用于计数,然后我们自动切换到构建偶数长度,并可以再次使用所有低位进行计数。每一个数字在反向添加后都将成为回文。它是如何计算的ate它将给出第n个回文?较长的回文具有较高的数值。回文的左“上”半部分对于相同长度内的顺序最为重要。因此,当我确保上半部分以正确的顺序生成(即计数)时,我确保回文的顺序正确。
0
1
11
101
1001
1111
...
1......1
for (int i = 1; i < mapping.length; i++) {
    mapping[i] = (long) (mapping[i - 1] + Math.pow(2, Math.ceil((i - 1) * 1.0 / 2)));
}
public static long magical(long n) {
    if (n == 0 || n == 1) {
        return n;
    }
    long N = n - 2;
    return Long.parseLong(concat(N), 2);
}

private static String concat(long N) {
    int midLen = Arrays.binarySearch(indexRange, N);
    if (midLen < 0) {
        midLen = -midLen - 1;
    }
    long remaining = N - indexRange[midLen];
    String mid = mirror(remaining, midLen);
    return '1' + mid + '1';
}

private static String mirror(long n, int midLen) {
    int halfLen = (int) Math.ceil(midLen * 1.0 / 2);
    // produce fixed length binary string
    final String half = Long.toBinaryString(n | (1 << halfLen)).substring(1);
    if (midLen % 2 == 0) {
        return half + new StringBuilder(half).reverse().toString();
    } else {
        return half + new StringBuilder(half).reverse().toString().substring(1);
    }
}