494. Target Sum(第十一周)

探讨如何通过递归算法解决符号组合求和问题,即给定一组非负整数及目标值S,寻找使得整数之和等于S的有效符号组合方式的数量。

Description:

You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.

Find out how many ways to assign symbols to make sum of integers equal to target S.

Example 1:

Input: nums is [1, 1, 1, 1, 1], S is 3. 
Output: 5
Explanation: 

-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

There are 5 ways to assign symbols to make the sum of nums be target 3.

Note:

  1. The length of the given array is positive and will not exceed 20.
  2. The sum of elements in the given array will not exceed 1000.
  3. Your output answer is guaranteed to be fitted in a 32-bit integer.
解题思路:

这道题要用到计算所有有可能出现的情况然后再比较,用递归可以做。时间复杂度为O(n^2)。

class Solution {
public:
	int result ;
    int findTargetSumWays(vector<int>& nums, int S) {
        dfs(0,0,nums,S);
        return result;
    }
    void dfs(int sum, int count, vector<int>&nums, int s){
    	if(count == nums.size()){
    		if(sum == s) result++;
    		return;
		}
		dfs(sum+nums[count], count+1, nums, s);
		dfs(sum-nums[count], count+1, nums, s);
	}
};
DECLARE v_1 DATE := TO_DATE('20250301', 'YYYYMMDD'); v_start DATE; v_end DATE := TRUNC(SYSDATE); v_current DATE; v_sql VARCHAR2(32767); -- 增大缓冲区大小 (5000 -> 32767) BEGIN v_start := TRUNC(v_1); FOR i IN 0..(v_end - v_start) LOOP v_current := v_start + i; v_sql := 'MERGE INTO FK_ADS.ADS_PURE_REPAYMENT_AMOUNT_DI_D dest USING ( WITH t1 AS ( SELECT a.*, CASE WHEN a.COUNTRY_CODE = ''tz'' THEN a.IN_FORCE_DATE + 3 / 24 WHEN a.COUNTRY_CODE = ''ke'' THEN a.IN_FORCE_DATE + 3 / 24 WHEN a.COUNTRY_CODE = ''ci'' THEN a.IN_FORCE_DATE WHEN a.COUNTRY_CODE = ''ph'' THEN a.IN_FORCE_DATE + 8 / 24 END AS NEW_DATE FROM GHANA_CASH.LOAN_BORROW_INFO a WHERE a.COUNTRY_CODE <> ''gh'' AND a.RISK_SERIAL_NO <> ''googleplay'' AND a.ARCHIVED = 1 AND a.IN_FORCE_DATE IS NOT NULL AND TRUNC(A.LAST_MODIFIED_DATE) < TRUNC(SYSDATE) ), t2 AS ( SELECT DISTINCT phone, country_code, NEW_DATE FROM t1 WHERE TRUNC(NEW_DATE) = TO_DATE(''' || TO_CHAR(v_current, 'YYYYMMDD') || ''', ''YYYYMMDD'') AND user_type_product = 0 ), t3 AS ( SELECT t1.NEW_DATE, t1.REPAYMENT_AMOUNT FROM t2 LEFT JOIN t1 ON t2.phone = t1.phone AND t2.country_code = t1.country_code AND t1.NEW_DATE >= t2.NEW_DATE AND t1.new_date IS NOT NULL ), t4 AS ( SELECT week_num, TO_DATE(''' || TO_CHAR(v_current, 'YYYYMMDD') || ''', ''YYYYMMDD'') AS pure_in_force_date, SUM(REPAYMENT_AMOUNT / 100) AS total_AMOUNT FROM ( SELECT REPAYMENT_AMOUNT, TRUNC((NEW_DATE - MIN(NEW_DATE) OVER ()) / 7) + 1 AS week_num FROM t3 WHERE NEW_DATE BETWEEN TO_DATE(''2025-03-01'', ''YYYY-MM-DD'') AND TRUNC(ADD_MONTHS(SYSDATE, 12), ''YYYY'') - 1 ) GROUP BY week_num ), t5 AS ( SELECT * FROM t4 PIVOT ( SUM(total_AMOUNT) FOR week_num IN ( 1 AS "第一", 2 AS "第二", 3 AS "第三", 4 AS "第四", 5 AS "第五", 6 AS "第六", 7 AS "第七", 8 AS "第八", 9 AS "第九", 10 AS "第十", 11 AS "第十一", 12 AS "第十二", 13 AS "第十三", 14 AS "第十四", 15 AS "第十五", 16 AS "第十六", 17 AS "第十七", 18 AS "第十八", 19 AS "第十九", 20 AS "第二十", 21 AS "第二十一", 22 AS "第二十二", 23 AS "第二十三", 24 AS "第二十四", 25 AS "第二十五", 26 AS "第二十六", 27 AS "第二十七", 28 AS "第二十八", 29 AS "第二十九", 30 AS "第三十", 31 AS "第三十一", 32 AS "第三十二", 33 AS "第三十三", 34 AS "第三十四", 35 AS "第三十五", 36 AS "第三十六", 37 AS "第三十七", 38 AS "第三十八", 39 AS "第三十九", 40 AS "第四十", 41 AS "第四十一", 42 AS "第四十二", 43 AS "第四十三" ) ) ) SELECT * FROM t5 ) src ON (dest.PURE_IN_FORCE_DATE = src.pure_in_force_date) WHEN MATCHED THEN UPDATE SET dest."第一" = src."第一", dest."第二" = src."第二", dest."第三" = src."第三", dest."第四" = src."第四", dest."第五" = src."第五", dest."第六" = src."第六", dest."第七" = src."第七", dest."第八" = src."第八", dest."第九" = src."第九", dest."第十" = src."第十", dest."第十一" = src."第十一", dest."第十二" = src."第十二", dest."第十三" = src."第十三", dest."第十四" = src."第十四", dest."第十五" = src."第十五", dest."第十六" = src."第十六", dest."第十七" = src."第十七", dest."第十八" = src."第十八", dest."第十九" = src."第十九", dest."第二十" = src."第二十", dest."第二十一" = src."第二十一", dest."第二十二" = src."第二十二", dest."第二十三" = src."第二十三", dest."第二十四" = src."第二十四", dest."第二十五" = src."第二十五", dest."第二十六" = src."第二十六", dest."第二十七" = src."第二十七", dest."第二十八" = src."第二十八", dest."第二十九" = src."第二十九", dest."第三十" = src."第三十", dest."第三十一" = src."第三十一", dest."第三十二" = src."第三十二", dest."第三十三" = src."第三十三", dest."第三十四" = src."第三十四", dest."第三十五" = src."第三十五", dest."第三十六" = src."第三十六", dest."第三十七" = src."第三十七", dest."第三十八" = src."第三十八", dest."第三十九" = src."第三十九", dest."第四十" = src."第四十", dest."第四十一" = src."第四十一", dest."第四十二" = src."第四十二", dest."第四十三" = src."第四十三" WHEN NOT MATCHED THEN INSERT ( pure_in_force_date, "第一","第二","第三","第四","第五","第六","第七","第八","第九","第十", "第十一","第十二","第十三","第十四","第十五","第十六","第十七","第十八","第十九","第二十", "第二十一","第二十二","第二十三","第二十四","第二十五","第二十六","第二十七","第二十八","第二十九","第三十", "第三十一","第三十二","第三十三","第三十四","第三十五","第三十六","第三十七","第三十八","第三十九","第四十", "第四十一","第四十二","第四十三" ) VALUES ( src.pure_in_force_date, src."第一",src."第二",src."第三",src."第四",src."第五",src."第六",src."第七",src."第八",src."第九",src."第十", src."第十一",src."第十二",src."第十三",src."第十四",src."第十五",src."第十六",src."第十七",src."第十八",src."第十九",src."第二十", src."第二十一",src."第二十二",src."第二十三",src."第二十四",src."第二十五",src."第二十六",src."第二十七",src."第二十八",src."第二十九",src."第三十", src."第三十一",src."第三十二",src."第三十三",src."第三十四",src."第三十五",src."第三十六",src."第三十七",src."第三十八",src."第三十九",src."第四十", src."第四十一",src."第四十二",src."第四十三" )'; EXECUTE IMMEDIATE v_sql; END LOOP; END;以下行中出错: 1: ORA-00932: 数据类型不一致: 应为 NUMBER, 但却获得 INTERVAL DAY TO SECOND ORA-06512: 在 line 140
06-12
<think>我们当前的问题是关于ORA-00932错误,即数据类型不一致。具体报错信息是“应为NUMBER但获得INTERVALDAYTOSECOND”。这个错误通常发生在我们试图将不兼容的数据类型进行赋值、比较或运算时。在用户提供的上下文中,错误发生在MERGEINTO语句中,可能涉及WITH子查询和动态SQL(EXECUTEIMMEDIATE)。根据Oracle文档,INTERVALDAYTOSECOND数据类型表示一段时间,以天、小时、分钟和秒为单位。而NUMBER是数值类型。当这两种类型在操作中不兼容时,就会出现ORA-00932。解决步骤:1.定位错误发生的具体位置:由于错误信息中提到期望NUMBER但得到INTERVALDAYTOSECOND,所以我们需要在MERGE语句中找到涉及这两种类型的列或表达式。2.检查MERGE语句中涉及的两个表(目标表和源表)的结构,特别是错误提示的列。需要确认目标表的列是NUMBER类型,而源数据却提供了INTERVALDAYTOSECOND类型。3.在WITH子查询中,检查生成源数据的部分,看是否有表达式产生了INTERVALDAYTOSECOND类型,但目标列需要的是NUMBER。4.如果使用了动态SQL(EXECUTEIMMEDIATE),那么需要检查动态SQL字符串中构建的部分,看是否在某个地方出现了类型不匹配。5.转换数据类型:如果确实需要将INTERVALDAYTOSECOND转换为NUMBER,我们可以使用Oracle提供的函数。例如,我们可以将时间间隔转换为秒数(NUMBER):EXTRACT(DAYFROMinterval_value)*86400+EXTRACT(HOURFROMinterval_value)*3600+EXTRACT(MINUTEFROMinterval_value)*60+EXTRACT(SECONDFROMinterval_value)但是注意:如果源数据是一个INTERVAL类型,那么我们应该检查业务逻辑,是否真的应该将其转换为数字(例如秒数)?或者目标列是否应该定义为INTERVAL类型?6.另一种情况:如果错误发生在比较操作中,比如MERGE语句的ON条件,那么需要确保比较的两边数据类型一致。例如,不要将INTERVAL类型与NUMBER类型直接比较。7.如果错误发生在动态SQL中,则可能更难发现。我们需要将动态SQL字符串打印出来(DBMS_OUTPUT)或者在执行前记录,以便检查。由于用户没有提供具体的代码,我将提供一个通用的修复方案:假设在MERGE语句的某个地方,有一个INTERVAL类型的列(例如DURATION)被当作NUMBER使用。那么我们可以通过转换函数将其转换为秒数(例如上面的方法)或者根据需求转换为其他数值。示例:假设源表(SOURCE_TABLE)中有一个名为DURATION的INTERVALDAYTOSECOND列,而目标表(TARGET_TABLE)的对应列是NUMBER类型,存储总秒数。我们可以这样转换:SELECT(EXTRACT(DAYFROMDURATION)*86400+EXTRACT(HOURFROMDURATION)*3600+EXTRACT(MINUTEFROMDURATION)*60+EXTRACT(SECONDFROMDURATION))ASDURATION_SECONDSFROMSOURCE_TABLE然后将这个转换后的列用于MERGE。但是,如果这个INTERVAL类型的值在动态SQL中生成,那么我们需要在动态SQL中做同样的转换。另外,如果目标列实际上应该是INTERVAL类型,但被错误定义为NUMBER,那么需要考虑修改表结构。由于问题描述有限,我们只能提供一般性建议。下面,我将写一个解决此类错误的步骤总结:步骤1:确定错误位置-检查整个SQL语句(包括WITH子查询),特别是ON条件和SET子句中的赋值。步骤2:验证目标列的数据类型-使用DESC命令或数据字典视图(如USER_TAB_COLUMNS)查看目标列的类型。步骤3:检查源数据的类型-使用DUMP函数或查看源表列的定义。步骤4:转换数据类型-如果必须将INTERVAL转换为NUMBER,按照上述方法转换。-或者,在必要的情况下,将NUMBER转换为INTERVAL(例如使用NUMTODSINTERVAL函数),但这取决于实际需求。步骤5:如果使用动态SQL,则确保转换在动态SQL字符串内完成。步骤6:重新测试。由于问题描述中未出现具体代码,我们无法提供更具体的修复。不过,如果用户能够提供具体的SQL片段,我们可以更精确地定位。注意:在Oracle中,使用EXTRACT函数处理INTERVAL类型时需要小心,因为EXTRACT返回的是数值,所以可以将其组合成一个总秒数。下面是一个将INTERVALDAYTOSECOND转换为总秒数的示例函数:CREATEORREPLACEFUNCTIONinterval_to_seconds(interval_inININTERVALDAYTOSECOND)RETURNNUMBERISdaysNUMBER;hoursNUMBER;minutesNUMBER;secondsNUMBER;BEGINdays:=EXTRACT(DAYFROMinterval_in);hours:=EXTRACT(HOURFROMinterval_in);minutes:=EXTRACT(MINUTEFROMinterval_in);seconds:=EXTRACT(SECONDFROMinterval_in);RETURN(days*86400)+(hours*3600)+(minutes*60)+seconds;END;然后可以在SQL中直接使用该函数转换。不过,我们也可以直接在SQL中写转换表达式而不创建函数。最后,如果用户的问题依然存在,请提供具体的SQL语句(尤其是MERGE和WITH部分),以及表结构(目标表和源表的对应列定义)。相关问题:1.Oracle中INTERVALDAYTOSECOND数据类型如何转换为NUMBER?2.如何避免MERGE语句中的数据类型转换错误?3.动态SQL中如何处理数据类型转换?4.EXTRACT函数的用法?</think> 针对 Oracle SQL 中的 **ORA-00932 数据类型不一致错误**(应为 NUMBER 但获得 INTERVAL DAY TO SECOND),以下是系统化的解决方案: --- ### 根本原因分析 该错误发生在 `MERGE INTO` 或 `EXECUTE IMMEDIATE` 语句中,当存在以下情况时: 1. **数据类型冲突**:NUMBER 列与 INTERVAL DAY TO SECOND 数据直接比较或赋值 (如:`number_col = INTERVAL '5' DAY`) 2. **隐式转换失败**:Oracle 无法自动将时间间隔值转为数值类型 (INTERVAL 类型存储为 `INTERVAL DAY(n) TO SECOND(m)` 格式,与 NUMBER 不兼容) 3. **动态SQL陷阱**:`EXECUTE IMMEDIATE` 在运行时才暴露类型错误,难以调试 --- ### 解决方案(分场景处理) #### 🟢 场景1:MERGE INTO 中的类型转换 在 `USING` 子查询中将 INTERVAL 显式转为 NUMBER: ```sql MERGE INTO target_table t USING ( SELECT id, -- 将INTERVAL转为秒数(示例:INTERVAL '5' DAY → 432000秒) EXTRACT(DAY FROM duration)*86400 + EXTRACT(HOUR FROM duration)*3600 + EXTRACT(MINUTE FROM duration)*60 + EXTRACT(SECOND FROM duration) AS duration_seconds FROM source_table ) s ON (t.id = s.id) WHEN MATCHED THEN UPDATE SET t.duration_num = s.duration_seconds; -- 赋值给NUMBER列 ``` #### 🟢 场景2:动态SQL中的类型安全 在 `EXECUTE IMMEDIATE` 前预处理 INTERVAL 数据: ```plsql DECLARE v_interval INTERVAL DAY TO SECOND := INTERVAL '5' DAY; v_seconds NUMBER; BEGIN -- 先转换为秒数再执行动态SQL v_seconds := EXTRACT(DAY FROM v_interval)*86400; EXECUTE IMMEDIATE ' UPDATE target_table SET num_col = :1 WHERE id = 100 ' USING v_seconds; -- 绑定NUMBER类型变量 END; ``` #### 🟢 场景3:确保比较操作兼容性 修改 `ON` 条件避免直接比较: ```sql MERGE INTO target_table t USING source_table s ON ( t.id = s.id -- 错误: AND t.num_col = s.interval_col ❌ -- 修正: 使用统一类型 AND t.num_col = EXTRACT(SECOND FROM s.interval_col)) ... ``` --- ### 关键诊断步骤 1. **定位问题列**: ```sql -- 检查目标表和源表的列定义 SELECT column_name, data_type FROM all_tab_columns WHERE table_name IN ('TARGET_TABLE', 'SOURCE_TABLE') AND column_name LIKE '%DURATION%'; -- 替换可疑列名 ``` 2. **验证转换逻辑**: ```sql -- 测试INTERVAL转NUMBER的表达式 SELECT interval_col, EXTRACT(DAY FROM interval_col)*86400 + EXTRACT(SECOND FROM interval_col) AS total_seconds FROM source_table WHERE ROWNUM = 1; ``` 3. **追踪动态SQL**: ```plsql -- 打印动态SQL语句以便调试 DBMS_OUTPUT.PUT_LINE('Dynamic SQL: ' || v_sql_stmt); ``` --- ### 预防措施 1. **显式类型转换**:始终在复杂操作前用 `EXTRACT()`/`NUMTODSINTERVAL()` 转换类型 2. **静态SQL优先**:避免动态SQL;必要时先用静态SQL测试类型兼容性 3. **列注释规范**: ```sql COMMENT ON COLUMN target_table.duration_num IS '存储秒数(由INTERVAL转换而来)'; ``` > **注意**:如果业务逻辑允许,可考虑修改表结构,直接使用 **NUMBER 存储秒数** 替代 INTERVAL 类型[^1]。 --- ### 类型转换参考公式 | 转换方向 | 函数 | 示例 | |---------|------|------| | **INTERVAL → NUMBER** | `EXTRACT()`组合 | $ \text{total\_seconds} = d \times 86400 + h \times 3600 + m \times 60 + s $ | | **NUMBER → INTERVAL** | `NUMTODSINTERVAL()` | `NUMTODSINTERVAL(500000, 'SECOND')` → `+05 18:53:20.000000` | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值