Java到1的最短路径
旧程序Java到1的最短路径,java,Java,旧程序 public class JavaApplication7 { public static void main(String[] args) { String n = ""; // any given whole positive integer long solution = 0; double t = Double.parseDouble(n); double pow = nearpow(t);
public class JavaApplication7 {
public static void main(String[] args) {
String n = ""; // any given whole positive integer
long solution = 0;
double t = Double.parseDouble(n);
double pow = nearpow(t);
double nearpow = Math.pow(2, nearpow(t));
double difference = Math.abs(t-nearpow);
while(t!=1){
if(t==nearpow){
solution+=pow;
t/=nearpow;
}
if(nearpow<t&&t!=1){
t = t - difference;
solution+=difference;
t = t / nearpow;
solution+=pow;
}
else if(nearpow>t&&t!=1){
t+=difference;
solution+=difference;
t/=nearpow;
solution+=pow;
}
}
System.out.println(solution);
}
public static double nearpow(double t){
double log = Math.log(t) / Math.log(2);
long roundLog = Math.round(log);
double dec = Math.abs(log-roundLog);
long lowPow = (long)(log-dec);
long highPow = lowPow+1;
if(Math.abs(t-Math.pow(2,highPow))<Math.abs(t-Math.pow(2,lowPow))){
return highPow;
}
else{
return lowPow;
}
}
}
String n = "54123";
BigInteger t = new BigInteger(n);
BigInteger one = new BigInteger("1");
System.out.println(t);
int solution =0;
while(!t.equals(one)){
if(((t.and(one)).equals(BigInteger.ZERO))){
System.out.println(t+"/2 =");
t=t.shiftRight(1);
solution++;
}
else if((t.and(one)).equals(BigInteger.ONE)&&(((t.shiftRight(1).and(one))).equals(BigInteger.ONE))&&(((t.shiftRight(2).and(one))).equals(BigInteger.ONE))){
System.out.println(t+"+2 =");
t=t.add(one);
solution++;
}
else if(t.and(one).shiftRight(1).equals(BigInteger.ZERO)&&t.and(one).equals(one)){
System.out.println(t+"-1 =");
t=t.subtract(one);
solution++;
}
}
System.out.print(solution);
我是位运算的新手,所以我需要一些帮助来找出问题的新缺点,因为我写的东西对我来说还是很新的,为了增加位运算的新用途,我必须用BigInteger来写,这些术语我很难理解,然而,对于我使用的术语,它应该可以工作,但我找不到一个不工作的原因,以前使用的示例是762,它给出了259个操作,而对于新程序,它给出了15个操作,由于术语的新颖性,我仍然难以识别故障。
我写的解决方案(作品)
这是一个位操作的问题,正如除以2规则所暗示的那样 让我们看一看注释中提到的编号
762
(基数10),即1011111010
(基数2)(现已删除)
除以2意味着将位向右移位。假设不允许这样做,除非数字可以被2整除,即最右边的位是0
所以,如果我们能右转,我们就能做到。如果不是,我们可以减去1来清除位
但是,如果下一位也为1,我们可以改为添加1,因此在一次操作中将多个1位翻转为0,例如100111+1=101000
作为一项特殊考虑,11
不应添加1
,因为这将是11
→ <代码>100→ <代码>10→ <代码>1,即3次操作。而是减去1
得到11
→ <代码>10→ <代码>1
1011111010
1: /2 = 101111101
2: -1 = 101111100
3: /2 = 10111110
4: /2 = 1011111
5: +1 = 1100000
6: /2 = 110000
7: /2 = 11000
8: /2 = 1100
9: /2 = 110
10: /2 = 11
11: -1 = 10
12: /2 = 1
在12操作中找到解决方案
现在您只需要为它编写代码。这是一个位操作的问题,正如除以2规则所暗示的那样 让我们看一看注释中提到的编号
762
(基数10),即1011111010
(基数2)(现已删除)
除以2意味着将位向右移位。假设不允许这样做,除非数字可以被2整除,即最右边的位是0
所以,如果我们能右转,我们就能做到。如果不是,我们可以减去1来清除位
但是,如果下一位也为1,我们可以改为添加1,因此在一次操作中将多个1位翻转为0,例如100111+1=101000
作为一项特殊考虑,11
不应添加1
,因为这将是11
→ <代码>100→ <代码>10→ <代码>1,即3次操作。而是减去1
得到11
→ <代码>10→ <代码>1
1011111010
1: /2 = 101111101
2: -1 = 101111100
3: /2 = 10111110
4: /2 = 1011111
5: +1 = 1100000
6: /2 = 110000
7: /2 = 11000
8: /2 = 1100
9: /2 = 110
10: /2 = 11
11: -1 = 10
12: /2 = 1
在12操作中找到解决方案
现在您只需为它编写代码。表达式
(!((t.and(one)).shiftRight(1)).equals(BigInteger.ZERO))
及
你错了。他们的目的是测试t
的第二和第三个最低有效位是否为非零,但他们没有。它们每次只返回false
这两个表达式都以t和(one)
开头,这将隔离t
的最后一位,而不是倒数第二位或倒数第三位。然后,每一位都将该位移开,实际上留下了biginger.ZERO
。因此,这两个测试都归结为biginger.ZERO.equals(biginger.ZERO)
,因为biginger.ZERO
永远不等于biginger.ZERO
,所以无论t
是什么,结果都是一致的false
你想要的是
(!((t.shiftRight(1)).and(one)).equals(BigInteger.ZERO))
及
执行移位操作时,首先将所需的t
位移动到之前新的BigInteger
中的最后一个位置,然后(一个)
将其隔离以进行测试。现在您实际上正在测试表达式的倒数第二位和倒数第三位
(!((t.and(one)).shiftRight(1)).equals(BigInteger.ZERO))
及
你错了。他们的目的是测试t
的第二和第三个最低有效位是否为非零,但他们没有。它们每次只返回false
这两个表达式都以t和(one)
开头,这将隔离t
的最后一位,而不是倒数第二位或倒数第三位。然后,每一位都将该位移开,实际上留下了biginger.ZERO
。因此,这两个测试都归结为biginger.ZERO.equals(biginger.ZERO)
,因为biginger.ZERO
永远不等于biginger.ZERO
,所以无论t
是什么,结果都是一致的false
你想要的是
(!((t.shiftRight(1)).and(one)).equals(BigInteger.ZERO))
及
执行移位操作时,首先将所需的
t
位移动到之前新的BigInteger
中的最后一个位置,然后(一个)
将其隔离以进行测试。现在您实际上正在测试t
的倒数第二位和倒数第三位。我编写了@Andreas按位方法的版本
public static enum Op
{
PLUS_1, MINUS_1, DIV_2
}
public static void shortest( final long value, final List<Op> steps )
{
System.out.println( Long.toBinaryString( value ) );
if ( value > 1L )
{
if ( ( value & 1L ) == 0L )
{
// last bit is 0
steps.add( Op.DIV_2 );
shortest( value / 2L, steps );
}
else if ( Long.highestOneBit( value ) == Long.bitCount( value ) )
{
// only 1 bits
steps.add( Op.MINUS_1 );
shortest( value - 1L, steps );
}
else if ( ( value & 3L ) == 3L )
{
// last bits are 11
steps.add( Op.PLUS_1 );
shortest( value + 1L, steps );
}
else
{
// last bits are 01
steps.add( Op.MINUS_1 );
shortest( value - 1L, steps );
}
}
}
public static void print( final long value, final List<Op> steps )
{
System.out.printf( "%d = %<x = %s = %d %s\n", value, Long.toBinaryString( value ),
steps.size(), steps );
}
public static void main( final String[] args )
{
final List<Op> steps = new ArrayList<>();
shortest( 726, steps );
print( 726, steps );
steps.clear();
shortest( 762, steps );
print( 762, steps );
}
我编写了@Andreas按位方法的版本
public static enum Op
{
PLUS_1, MINUS_1, DIV_2
}
public static void shortest( final long value, final List<Op> steps )
{
System.out.println( Long.toBinaryString( value ) );
if ( value > 1L )
{
if ( ( value & 1L ) == 0L )
{
// last bit is 0
steps.add( Op.DIV_2 );
shortest( value / 2L, steps );
}
else if ( Long.highestOneBit( value ) == Long.bitCount( value ) )
{
// only 1 bits
steps.add( Op.MINUS_1 );
shortest( value - 1L, steps );
}
else if ( ( value & 3L ) == 3L )
{
// last bits are 11
steps.add( Op.PLUS_1 );
shortest( value + 1L, steps );
}
else
{
// last bits are 01
steps.add( Op.MINUS_1 );
shortest( value - 1L, steps );
}
}
}
public static void print( final long value, final List<Op> steps )
{
System.out.printf( "%d = %<x = %s = %d %s\n", value, Long.toBinaryString( value ),
steps.size(), steps );
}
public static void main( final String[] args )
{
final List<Op> steps = new ArrayList<>();
shortest( 726, steps );
print( 726, steps );
steps.clear();
shortest( 762, steps );
print( 762, steps );
}
它是如何失败的?举一个具体的例子。你知道失败的确切临界值吗?将所有相关信息编辑到你的问题中,使其完整。顺便说一句,我想从我的@s$中猜出最小值是
k+(n-2^k)
其中n
是你的数字,k=floor(log2(n))
k
是除以2的除数,而n-2^k
是数字离电源有多远
1011010110
101101011
101101100
10110110
1011011
1011100
101110
10111
11000
1100
110
11
10
1
726 = 2d6 = 1011010110 = 13 [DIV_2, PLUS_1, DIV_2, DIV_2, PLUS_1, DIV_2, DIV_2, PLUS_1, DIV_2, DIV_2, DIV_2, MINUS_1, DIV_2]
1011111010
101111101
101111100
10111110
1011111
1100000
110000
11000
1100
110
11
10
1
762 = 2fa = 1011111010 = 12 [DIV_2, MINUS_1, DIV_2, DIV_2, PLUS_1, DIV_2, DIV_2, DIV_2, DIV_2, DIV_2, MINUS_1, DIV_2]