求修复Kotlin四数拆分函数以通过指定单元测试
修复Kotlin拆分4个不同正整数的函数问题
问题背景
需要实现函数divideIntoFourDistinctNumbersThatAddUptoTotal,将给定的total(范围10~50)拆分为4个互不相同的正整数,满足以下单元测试要求:
@Test fun dividingIntoFour() { repeat(times = 100) { val randomNumber = Random.nextInt(from = 50, until = 90) val total = 100 - randomNumber val numberList = divideIntoFourDistinctNumbersThatAddUptoTotal(total = total) assert(numberList.sum() == total) assert(!numberList.contains(0)) assert(numberList.all { it > 0 }) assert(numberList.distinct().size == 4) } }
原实现存在偶尔挂起的问题,根源在于最后一个while循环的调整逻辑可能陷入死循环,同时初始选数范围未考虑边界情况(可能生成无效数值范围)。
原代码问题分析
- 无效范围风险:当
total较小时(比如10),计算aTotal后可能生成start > end的Range(如3..2),调用random()会直接抛出异常。 - 死循环隐患:最后一个
while循环的调整逻辑(如fourth -=1、first +=1)可能导致数值重复问题反复出现,或者将数值调整为0/负数,无法跳出循环。 - 边界条件缺失:未确保剩余数值能满足正整数要求,可能生成非正整数。
解决方案
采用循环重试+边界约束的方式,确保每次生成的数值都符合要求,且不会陷入死循环:
import kotlin.random.Random fun divideIntoFourDistinctNumbersThatAddUptoTotal(total: Int): List<Int> { // 题目中total范围是10~50,满足最小拆分1+2+3+4=10的要求 require(total >= 10) { "Total must be at least 10 to split into 4 distinct positive integers" } val random = Random.Default while (true) { // 第一个数:范围1到total-6(剩余三个数至少需要1+2+3=6) val first = random.nextInt(1, total - 5) // 第二个数:范围1到total-first-3(剩余两个数至少需要1+2=3),且不等于first val second = generateSequence { random.nextInt(1, total - first - 2) } .first { it != first } // 第三个数:范围1到total-first-second-1(第四个数至少需要1),且不等于first、second val third = generateSequence { random.nextInt(1, total - first - second) } .first { it != first && it != second } // 计算第四个数 val fourth = total - first - second - third // 验证第四个数是否符合要求:正整数且与前三个都不同 if (fourth > 0 && fourth != first && fourth != second && fourth != third) { return listOf(first, second, third, fourth) } } }
方案优势
- 无死循环风险:由于题目中
total范围是10~50,必然存在有效拆分(如1,2,3,total-6),因此循环一定会找到符合条件的组合后退出。 - 边界安全:每个数的生成范围都确保剩余数值能满足正整数要求,避免出现0或负数。
- 严格去重:通过
generateSequence确保前三个数互不相同,最后验证第四个数的唯一性,保证最终列表的4个元素完全不同。 - 满足测试要求:生成的列表天然满足
sum == total、全正整数、无重复的条件。
内容的提问来源于stack exchange,提问作者Christopher Hall
相关产品推荐
相关产品推荐

