964. Least Operators to Express Number

本文探讨了一个数学问题,即如何使用最少的操作(加、减、乘、除)将给定的正整数x通过一系列运算达到目标值。文章提供了解决方案,通过递归算法和动态规划来找到最短的表达式,同时避免使用负号和确保运算顺序遵循常规的运算规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a single positive integer x, we will write an expression of the form x (op1) x (op2) x (op3) x ... where each operator op1op2, etc. is either addition, subtraction, multiplication, or division (+-*, or /).  For example, with x = 3, we might write 3 * 3 / 3 + 3 - 3 which is a value of 3.

When writing such an expression, we adhere to the following conventions:

  1. The division operator (/) returns rational numbers.
  2. There are no parentheses placed anywhere.
  3. We use the usual order of operations: multiplication and division happens before addition and subtraction.
  4. It's not allowed to use the unary negation operator (-).  For example, "x - x" is a valid expression as it only uses subtraction, but "-x + x" is not because it uses negation.

We would like to write an expression with the least number of operators such that the expression equals the given target.  Return the least number of expressions used.

 

Example 1:

Input: x = 3, target = 19
Output: 5
Explanation: 3 * 3 + 3 * 3 + 3 / 3.  The expression contains 5 operations.

Example 2:

Input: x = 5, target = 501
Output: 8
Explanation: 5 * 5 * 5 * 5 - 5 * 5 * 5 + 5 / 5.  The expression contains 8 operations.

Example 3:

Input: x = 100, target = 100000000
Output: 3
Explanation: 100 * 100 * 100 * 100.  The expression contains 3 operations.

 

Note:

  • 2 <= x <= 100
  • 1 <= target <= 2 * 10^8

思路:

1一定是通过x/x得到,然后剩下的部分一定是x的倍数,除以x的余数一定通过1得到,所以比赛的时候一直想的是划分成若干层,比如x = 3, target = 19:先求6+1,因为3*6+1=19,但是随着层数的嵌套,实际用了多少符号变得不好求了。

Discuss里的答案:独立考虑每个x的次幂使用的个数。具体来说:

求出x的整数次幂数组(一直求到比target大的那个数)A,然后从后往前考虑A,每次考虑用不用当前这个A[i],假设还剩下left需要求出来,那就可以有left/A[i]个A[i],或者(left/A[i])+1个A[i](超过left用减法)

注意:对于每个次幂,前面会加一个符号,比如用3*3*3的时候,在算的时候用的是+3*3*3或者-3*3*3;然而最后算完之后要把前面那个多余的符号去掉,对应 elif y == 0:return -1 这行代码

import functools
import math
class Solution(object):
    @functools.lru_cache(None)
    def leastOpsExpressTarget(self, x, y):
        """
        :type x: int
        :type target: int
        :rtype: int
        """
        k = int(math.log(y, x)) + 1
        def dfs(y, k):
            if k == 0:  return y + y - 1
            elif y == 0:return -1
            need, left = divmod(y, x**k)
            return min(dfs(left, k - 1) + need * k, dfs(x**k - left, k - 1) + (need + 1) * k)
        return dfs(y, k)
    
s=Solution()
print(s.leastOpsExpressTarget(x = 3, y = 19))
import math
class Solution(object):
    def leastOpsExpressTarget(self, x, y):
        """
        :type x: int
        :type target: int
        :rtype: int
        """
        k = int(math.log(y, x)) + 1
        memo = {}
        def dfs(y, k):
            if (y,k) in memo: return memo[(y,k)]
            if k == 0:  return y + y - 1
            elif y == 0:return -1
            need, left = divmod(y, x**k)
            res = min(dfs(left, k - 1) + need * k, dfs(x**k - left, k - 1) + (need + 1) * k)
            memo[(y,k)] = res
            return res
        return dfs(y, k)
    
s=Solution()
print(s.leastOpsExpressTarget(x = 3, y = 19))

有了memo的形式,也可以换成DP

<think>我们正在解决的是使用JSqlParser时出现的“未检查调用”警告(unchecked call warning)问题。具体来说,当我们创建`ExpressionList`对象时,可能会遇到类似以下的警告: ExpressionList<> expressionList = new ExpressionList(); // 警告信息:未经检查的调用 这是因为在Java中,当我们使用泛型类而没有指定具体类型参数时,编译器会发出未检查的警告。在JSqlParser中,`ExpressionList`是一个泛型类,其定义为: public class ExpressionList<E extends Expression> implements ItemsList, ... { ... } 因此,在创建`ExpressionList`实例时,我们应该提供具体的类型参数,以避免警告。 但是,在JSqlParser 5.0中,我们通常使用`Expression`作为类型参数,因为`ExpressionList`可以包含任何类型的表达式(Expression)。 所以,正确的创建方式应该是: ExpressionList<Expression> valList = new ExpressionList<>(); 然后,将表达式添加到这个列表中。 然而,在构造`InExpression`时,我们可能会这样写: InExpression inExp = new InExpression(new Column(column), valList); 注意:`InExpression`的构造函数接受一个`ItemsList`作为第二个参数,而`ExpressionList`实现了`ItemsList`接口,因此可以直接传入。 但是,如果我们没有指定泛型类型,就会产生警告。因此,我们需要在创建`ExpressionList`时指定泛型类型。 下面是一个完整的示例代码,展示如何避免未检查调用警告: ```java import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.schema.Column; import java.util.Arrays; public class FixExpressionListWarning { public static void main(String[] args) { // 创建一个ExpressionList,并指定泛型类型为Expression ExpressionList<Expression> valList = new ExpressionList<>(); // 添加一些表达式,例如LongValue(数值字面量) valList.setExpressions(Arrays.asList(new LongValue(1), new LongValue(2), new LongValue(3))); // 创建InExpression InExpression inExp = new InExpression(new Column("my_column"), valList); // 打印生成的SQL System.out.println(inExp.toString()); // 输出: my_column IN (1, 2, 3) } } ``` 这样,我们就避免了未检查调用的警告,因为我们在创建`ExpressionList`时明确指定了类型参数为`Expression`。 另外,如果使用`Arrays.asList`来初始化表达式列表,也可以直接在创建`ExpressionList`时传入,并指定类型: ```java ExpressionList<Expression> valList = new ExpressionList<>(Arrays.asList( new LongValue(1), new LongValue(2), new LongValue(3) )); ``` 这样代码更简洁。 注意:在JSqlParser 5.0中,`ExpressionList`的构造函数接受一个`List<Expression>`,所以我们可以这样传递。 总结:要修复未检查调用警告,只需在创建`ExpressionList`时指定泛型类型为`Expression`即可。 如果问题仍然存在,请检查代码中是否还有其他地方使用了未指定泛型类型的集合类,并按照相同方法修复。 §§相关问题§§ 1. 在JSqlParser中,如何处理不同类型的表达式(如字符串、日期)? 2. 如何避免JSqlParser解析SQL时出现的其他常见警告或错误? 3. JSqlParser支持哪些数据库的SQL语法?</think>### 解决 JSqlParser ExpressionList 未检查调用警告问题 在 JSqlParser 中使用 `ExpressionList` 时出现的 "unchecked call" 警告是 Java 泛型类型安全机制导致的常见问题。以下是完整解决方案: #### 问题原因分析 - **泛型类型擦除**:Java 编译器无法在运行时验证泛型类型,当使用 `ExpressionList` 而未指定具体类型时,会触发警告[^1] - **警告示例**: ```java // 产生警告的代码 ExpressionList valList = new ExpressionList(); // 未指定泛型类型 ``` - **警告信息**: `Note: Some input files use unchecked or unsafe operations. Recompile with -Xlint:unchecked for details.` #### 解决方案 以下是三种逐步修复方法,推荐使用**方法1**作为最佳实践: ##### 方法 1: 明确指定泛型类型(推荐) ```java // 明确指定泛型类型为 Expression ExpressionList<Expression> valList = new ExpressionList<>(); // 添加元素时自动类型检查 valList.add(new StringValue("value1")); valList.add(new LongValue(100)); // 构造 InExpression InExpression inExp = new InExpression( new Column("column_name"), valList // 类型安全 ); ``` **优点**: - 完全消除警告 - 编译时类型检查 - 兼容 JSqlParser 5.0+ 所有版本[^1] ##### 方法 2: 使用 @SuppressWarnings 注解(临时方案) ```java @SuppressWarnings("unchecked") public void createExpression() { // 临时禁用警告 ExpressionList valList = new ExpressionList(); valList.add(new DoubleValue(3.14)); InExpression inExp = new InExpression( new Column("price"), valList ); } ``` **适用场景**: - 遗留代码快速修复 - 无法修改泛型声明的特殊情况 - **注意**:应尽量限制注解作用范围(方法级优于类级) ##### 方法 3: 类型安全的表达式构建器 ```java public class SafeExpressionBuilder { public static ExpressionList<Expression> createList(Expression... exprs) { ExpressionList<Expression> list = new ExpressionList<>(); for (Expression expr : exprs) { list.add(expr); } return list; } } // 使用构建器 ExpressionList<Expression> valList = SafeExpressionBuilder.createList( new StringValue("A"), new StringValue("B") ); ``` **优势**: - 集中管理类型安全 - 支持批量添加表达式 - 减少重复代码 #### 完整示例 ```java import net.sf.jsqlparser.expression.*; import net.sf.jsqlparser.expression.operators.relational.*; import net.sf.jsqlparser.schema.Column; public class FixUncheckedWarning { public static void main(String[] args) { // 1. 创建类型安全的表达式列表 ExpressionList<Expression> statusValues = new ExpressionList<>(); statusValues.add(new LongValue(1)); statusValues.add(new LongValue(2)); statusValues.add(new LongValue(3)); // 2. 构造IN表达式 InExpression statusIn = new InExpression( new Column("order_status"), statusValues ); // 3. 构建完整WHERE子句 System.out.println("WHERE " + statusIn); // 输出: WHERE order_status IN (1, 2, 3) } } ``` #### 关键注意事项 1. **JSqlParser 版本兼容性** - 5.0+ 版本强化了泛型支持,建议升级到最新版本(当前 5.0.1) - 检查依赖:`implementation 'com.github.jsqlparser:jsqlparser:5.0.1'` 2. **表达式类型一致性** - 确保 `ExpressionList` 内元素均为 `Expression` 子类 - 常见有效类型: - `StringValue`:字符串值 - `LongValue`:整数值 - `DoubleValue`:浮点数值 - `Column`:列引用 - `Function`:SQL函数 3. **复杂场景处理** ```java // 混合类型表达式列表 ExpressionList<Expression> mixedList = new ExpressionList<>(); mixedList.add(new Column("user_id")); // 列引用 mixedList.add(new Function("MAX(order_id)")); // SQL函数 mixedList.add(new StringValue("active")); // 字符串 ``` 通过明确指定泛型类型 `ExpressionList<Expression>`,可彻底消除未检查调用警告,同时保持代码类型安全。建议结合 JSqlParser 官方文档验证实现:[JSqlParser GitHub](https://github.com/JSQLParser/JSqlParser)[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值