不用除法的算法题

题目来自网络,据说是腾讯2012年的面试题

问题描述:两个数组a[N],b[N],其中A[N]的各个元素值已知,现给b[i]赋值,b[i] = a[0]*a[1]*a[2]...*a[N-1]/a[i];要求:1.不准用除法运算2.除了循环计数值,a[N],b[N]外,不准再用其他任何变量(包括局部变量,全局变量等)3.满足时间复杂度O(n),空间复杂度O(1)

分析:

a0 * * * *

* a1 * * *

* * a2 * *

* * * a3 *

* * * * a4


如上图所示,首先,我们可以计算下三角(b的一个因子)

b0 = 1;

b1 = a0;

b2 = b1* a2;

....

得到(b0,b1,b2,...,bn-1)

然后计算上三角时,可以得到

bn-1 已经得到

bn-2 = bn-2 * an-1;

bn-3 = bn-1 * an-2    (an -2 需要更新为an-1*an-2)

bn-4 = bn-2 * an-3   (an -3 需要更新为an-2*an-3)

...

b0 = b0 * a1 (a1需要更新为a1*a2)

这样我们就可以得到结果了。


### 蛮力法算法的练习题与示例代码 蛮力法(Brute Force)是一种直接解决问题的方法,它通过枚举所有可能的解并逐一验证来找到正确的答案。这种方法虽然效率较低,但其简单性和通用性使其成为学习算法的良好起点。 以下是一个典型的蛮力法问题及其解决方案: #### 问题描述 **7-11店问题**:找到四个正数 \(a, b, c, d\),使得它们的和与积均等于 7.11。即满足以下条件: \[ a + b + c + d = 7.11 \] \[ a \times b \times c \times d = 7.11 \] #### 示例代码实现 以下为使用 C 语言实现的蛮力法解决方案[^1]: ```c #include <stdio.h> int main() { double sum = 7.11; int scale = 1000; // 将浮点数转换为整数以避免精度问题 int target_sum = (int)(sum * scale); int target_product = (int)(sum * scale); for (int a = 1; a <= target_sum; a++) { for (int b = 1; b <= target_sum - a; b++) { for (int c = 1; c <= target_sum - a - b; c++) { int d = target_sum - a - b - c; if (d > 0 && a * b * c * d == target_product) { printf("Solution found: %.3lf, %.3lf, %.3lf, %.3lf\n", a / (double)scale, b / (double)scale, c / (double)scale, d / (double)scale); } } } } return 0; } ``` #### 解释 1. **精度处理**:为了避免浮点数运算中的精度问题,将所有数值乘以 1000 并转换为整数进行计算。 2. **嵌套循环**:通过三重嵌套循环枚举 \(a, b, c\) 的值,并根据和的约束条件计算 \(d\)。 3. **验证条件**:在每次循环中检查是否满足和与积的条件。 --- #### 链表相关问题的蛮力法应用 在链表操作中,蛮力法通常用于直接遍历节点以解决问题。例如,在链表反转问题中,可以通过逐个节点操作完成任务。尽管这不是最优方法,但在某些情况下仍然适用[^2]。 以下为链表反转的蛮力法实现: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def reverse_list(head): prev = None current = head while current is not None: next_node = current.next # 暂存下一个节点 current.next = prev # 反转指针 prev = current # 移动 prev 和 current current = next_node return prev ``` #### 解释 1. **指针反转**:通过维护 `prev` 和 `current` 指针,逐步反转链表的每个节点。 2. **时间复杂度**:该方法的时间复杂度为 \(O(n)\),其中 \(n\) 是链表的长度。 --- #### 后缀表达式求值的蛮力法 后缀表达式求值是栈的经典应用场景之一。通过蛮力法可以直接模拟栈的操作过程,确保每个运算符都能正确获取其操作数[^3]。 以下为 Python 实现的后缀表达式求值代码: ```python from typing import List class Solution: def evalRPN(self, tokens: List[str]) -> int: def comp(op1, op, op2): if op == '+': return op1 + op2 if op == '-': return op1 - op2 if op == '*': return op1 * op2 if op == '/': abs_result = abs(op1) // abs(op2) return abs_result if op1 * op2 > 0 else -abs_result stack = [] for token in tokens: if token in ['+', '-', '*', '/']: op2 = stack.pop() op1 = stack.pop() stack.append(comp(op1, token, op2)) else: stack.append(int(token)) return stack[0] # 测试用例 tokens = ["2", "1", "+", "3", "*"] solution = Solution() print(solution.evalRPN(tokens)) # 输出: 9 ``` #### 解释 1. **栈操作**:通过栈存储操作数,并在遇到运算符时弹出两个操作数进行计算。 2. **除法截断**:为了处理整数除法的截断问题,需特别注意符号位的影响。 --- ### 总结 蛮力法虽然效率较低,但在许多场景下可以作为问题解决的起点。上述三个示例分别展示了蛮力法在浮点数问题、链表操作和后缀表达式求值中的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值