用最少的运算将数字m转换为n。允许的运算为1减乘以2。
例如:4和6。答案为2。第一操作:-1-> 4-1 =3。第二操作:*-> 3 * 2 = 6。
我对特定的输入(src = 26,dst = 5)使用BFS方法,这需要花费很长时间。难道我做错了什么?
from queue_class import queue class node: def __init__(self, value, level, parent): self.level = level self.value = value self.parent = parent def get_minimum_distance(src, target, q): if src == target: return 0 seen_list = [] data = node(src, 0, -1) q.enqueue(data) while not q.isempty(): data = q.dequeue() if data == "sentinel": break if data.value == target: # let's print what has got me here while data.parent != -1: print(data.value) data = data.parent return "finally reached" if data.value in seen_list: continue seen_list.append(data.value) # two operations are allowed i.e. -1 and multiplication by 2 # check if two numbers have opposite sign and if they have # then check if the current number being subtracted from is a negative # number. If it is, then there is no point subtracting 1 from that if ((data.value ^ target) < 0 and data.value > 0) or (data.value ^ target >= 0): q.enqueue(node(data.value - 1, data.level + 1, data)) q.enqueue(node(data.value * 2, data.level + 1, data)) return -1 q = queue(1 << 20) print(get_minimum_distance(26, 5, q))
队列实现在这里完成。
感谢Paul:以下是我在python中使用以下代码编写的代码,它可以完美运行。
def get_minimum_operations(src, dst): step = 0 operations = [] if src == dst: return 0 if dst < src: return src-dst while dst > src: if dst & 0x01: step += 1 operations.append("-1") dst = (dst+1) >> 1 operations.append("*2") step += 1 for i in range(0, src-dst): operations.append("-1") return (((src - dst) + step), operations) src = 38 dst = 100 output = "" (steps, operations) = get_minimum_operations(src, dst) print(steps) try: while operations: i = operations.pop() if i == "*2": if output == "": output += "(" + str(src) + "*2" + ")" else: output = "(" + output + "*2" + ")" if i == "-1": if output == "": output += "(" + str(src) + "-1" + ")" else: output = "(" + output + "-1" + ")" except IndexError: pass print(output)
由于指数增长(这里进行了尝试2 ^ (n - 1) to 2^n,其中n是所需步骤的数量),因此BFS并不是完全正确的选择。而是尝试查找用于生成所需数字的逻辑规则。
2 ^ (n - 1) to 2^n
让我们a在输入号码和b应产生的数量。
a
b
有以下三种情况:
a == b
a > b
a - b
-1
a < b
最少数量的运算需要最少数量的乘法和减法。Substractions可以很容易地最小化由于以下事实:(a - 1) * 2 = a * 2 - 2。因此,通过在乘法之前简单地进行减法运算,我们可以轻松地将减法运算的数量减少2的幂。 由于我们只能减去和相乘,因此最小乘法数为min n => a * 2 ^ n >= b。 利用这个事实,我们可以确定要减去的金额:s = b - 2 ^ n * a。
(a - 1) * 2 = a * 2 - 2
min n => a * 2 ^ n >= b
s = b - 2 ^ n * a
该实现在伪代码中看起来像这样(无法提供python代码):
//using the same variable-names as above in the description minOp(int a , int b) //find minimum number of multiplications int n for(n = 0 ; a << n < b ; n++) noop //find amount to substract int s = (a << n) - b for(int i = 0 ; i < n ; i++) print("(") print(a) //calculate operations while(n > 0) //calculate number of times we need to substract here (minimization of substractions) while(s >= 1 << n) print(" - 1") s -= 1 << n print(")") //divide by two print(" * 2") n -= 1 while(s >= 1 << n) print(" - 1") s -= 1 << n print(" = ") print(b)
此实现藏汉覆盖情况a == b-与n = 0和s = 0-和a > b-与n = 0和s = a - b。
n = 0
s = 0
s = a - b
在上述的Java实现中进行测试运行将产生以下输出:
((((4) 2-1) 2-1)* 2 = 26
上面计算的简化显示了该算法的思想:
((4 * 2 - 1) * 2 - 1) * 2 = 26 (4 * 2 * 2 - 2 - 1) * 2 = 26 4 * 2 * 2 * 2 - 3 * 2 = 26 32 - 6 = 26
感谢@ user3386109的解释: 假设起始值为A,目标值为B。第一步是创建一个从B开始的目标值列表,然后除以2(如有必要,四舍五入)。 。例如,如果B为26,则目标值列表将为26、13、7、4、2、1。如果起始值A是这些目标值中的任何一个,则可以轻松地爬升至目标B(乘以2并在必要时减去1)。如果A不是这些值之一,则从A减去1开始,直到达到这些目标值之一。例如,如果A为6,则需要两个减法才能达到4,然后从4爬到26。如果A为12,则需要五个减法才能达到7,依此类推。显然,如果A大于B,那么您要做的就是减去1直到达到B