Problem overview
The function biggestDigitSum receives an array of integers nums and returns the number whose digits add up to the most. The digit sum of 472 is 4 + 7 + 2 = 13. If two numbers have the same digit sum, the one that comes first wins. The function returns the number itself, not its digit sum.
For [472, 95, 1000] the digit sums are 13, 14 and 1, so the answer is 95. For [19, 55, 28] all three sums are 10, so the first one, 19, wins. For [0, 7] the sums are 0 and 7, so the answer is 7. Every number is between 0 and 1,000,000,000.
Approach: a helper, then the best so far
The work is split in two. The helper digitSum turns one number into the sum of its digits. biggestDigitSum then walks through the array, remembering the number with the biggest digit sum seen so far.
To take a number apart, use two facts about whole numbers. n % 10 is the last digit, and n / 10 drops the last digit, since division of two Int values discards the remainder. For 472: 472 % 10 is 2 and 472 / 10 is 47. Repeat until nothing is left.
Step by step
- Copy the parameter. Swift function parameters are constants, so the loop can't change
n. Declarevar num = nand take digits offnum. - Start the total with
var total = 0. Forn = 0the loop never runs and 0 is the right answer. - Loop while
num > 0. Each turn removes one digit. - Add the last digit:
total += num % 10. - Drop the last digit:
num = num / 10. Without this line the loop never ends. - Return
total. - In
biggestDigitSum, startvar best = nums[0], the first number. - Loop over every number. The first is compared with itself, which changes nothing.
- Replace
bestwhendigitSum(num) > digitSum(best). Using>and not>=keeps the earlier number on a tie. - Return
best, the number itself.
The solution in Swift
class Solution {
func digitSum(_ n: Int) -> Int {
var num = n
var total = 0
while num > 0 {
total += num % 10
num = num / 10
}
return total
}
func biggestDigitSum(_ nums: [Int]) -> Int {
var best = nums[0]
for num in nums {
if digitSum(num) > digitSum(best) {
best = num
}
}
return best
}
}
Swift details: nums[0] is safe because the lesson guarantees at least one number. On an empty array it would crash the program. Integer division truncates toward zero. For the non-negative numbers here that is the same as flooring, but for a negative number the loop would not run at all, because num > 0 is false.
Tracing one number
For 472 the loop runs three times. It takes 2 and leaves 47, then takes 7 and leaves 4, then takes 4 and leaves 0. The total is 2 + 7 + 4 = 13, and the loop stops because num is 0.
Why the tie rule needs >
For [19, 55, 28] the digit sums are 10, 10 and 10. The loop starts with best equal to 19. Reaching 55, it asks whether 10 is greater than 10, which is false, so 19 stays. The same happens at 28. The first number with the top sum is the one that survives, as the lesson requires.
Why a helper is worth it
Splitting the digit loop into digitSum keeps biggestDigitSum short: one loop and one comparison. The helper is called twice per number, once for num and once for best. That repeats some work, which is fine for a short array. Storing the best sum in its own variable would avoid it, but the lesson's version stays simple.
These calls give:
95
19
7
for [472, 95, 1000], [19, 55, 28] and [0, 7]. Directly, digitSum(472) is 13, digitSum(0) is 0, digitSum(1000000000) is 1 and digitSum(999999999) is 81.
Another way to get the digits
The lesson takes digits off with % and /. Swift also lets you turn the number into text and read each character as a digit: String(n).compactMap { $0.wholeNumberValue }.reduce(0, +). It returns 13 for 472, 0 for 0 and 1 for 1,000,000,000, the same as the loop. The arithmetic version avoids creating a string and shows the idea that carries over to other languages, so it is the one to learn first.
Edge cases
Zero has a digit sum of 0, and the loop in digitSum handles it without special code, because 0 > 0 is false and the loop never runs. A number made of nines, such as 999,999,999, has the biggest possible digit sum here, 81. An array with one number returns that number, since best starts there and nothing can replace it.
Comparing sums, not numbers
The biggest number is not always the answer. In the first example 1000 is the largest number, but its digits sum to only 1, while 95 sums to 14. The condition compares digitSum(num) with digitSum(best), never num with best.
Common mistakes
- Returning the digit sum. The function returns the number, so
[472, 95, 1000]gives 95, not 14. - Using
>=. On a tie the later number would replace the earlier one, so[19, 55, 28]would return 28. - Forgetting
num = num / 10. The loop would run forever. - Trying to assign to
n. A parameter is a constant, and the compiler rejects it.
