Problem overview
The function maxValNumOfOccurrences receives a slice of integers, nums, and returns a two-element slice: the largest value, followed by how many times that value appears.
For nums = [2, 7, 11, 8, 11, 8, 3, 11] the largest value is 11, and it appears three times, so the result is [11, 3]. The statement asks for O(n) time and O(1) extra space, and the follow-up asks for a single pass over the slice.
Approach
The simple route uses two loops. The first finds the maximum, the way you would find the smallest of three numbers: keep a variable with the best value so far and replace it whenever something larger shows up. The second loop counts the elements equal to that maximum. Both loops are O(n), so this already meets the time budget, but it reads the data twice.
The one-pass version keeps the count up to date while the maximum is still being searched. Two things can happen for each element val:
valis larger thanmaxVal. A new maximum has appeared, somaxValbecomesval, and the count restarts at 1 because every earlier occurrence belonged to a smaller value.valequalsmaxVal. It's one more occurrence of the current maximum, so the count goes up by one.
Anything smaller than maxVal changes nothing. Tracing [2, 7, 11, 8, 11]:
val=2 maxVal=2 count=1
val=7 maxVal=7 count=1
val=11 maxVal=11 count=1
val=8 maxVal=11 count=1
val=11 maxVal=11 count=2
Step by step
- Declare
maxValandcounttogether with one:=.maxValstarts asnums[0], a real element, andcountstarts at 0. - Loop over the slice with
range, naming the elementvaland discarding the index with_. - Check for a new maximum:
val > maxVal. The comparison is strict, since an equal value isn't a new maximum, only another occurrence. - Handle it: set
maxValtovalandcountto 1. - Add the
else ifbranch forval == maxVal, and incrementcountwith++. - Return a slice literal of type
[]intwithmaxValandcount, in that order.
Starting count at 0 is deliberate. The loop visits nums[0] too. It equals maxVal, so the else if branch counts it, and the count is already 1 when the second element arrives.
The solution in Go
func maxValNumOfOccurrences(nums []int) []int {
maxVal, count := nums[0], 0
for _, val := range nums {
if val > maxVal {
maxVal = val
count = 1
} else if val == maxVal {
count++
}
}
return []int{maxVal, count}
}
The Go details worth a closer look:
- Multiple declaration. In
maxVal, count := nums[0], 0, the values on the right are assigned to the names on the left in order. Both variables are new, so:=is allowed. rangeyields an index and a value. For a slice,for i, val := range numsgives the position and a copy of the element. Go rejects unused variables, so an index you don't need goes into the blank identifier_.else ifstays on the closing brace's line. Write} else if val == maxVal {. A newline between}andelseis a syntax error, because Go inserts a semicolon at the end of that line.count++is a statement. It can't be used inside an expression, and there's no prefix++countin Go.- Returning two values. The lesson returns one slice,
[]int{maxVal, count}. Go functions can also return several values directly, but the tests expect a slice here.
Complexity
Time: O(n). The loop touches each element once and does a constant amount of work for each. Space: O(1). Besides the returned two-element slice, the function uses two integers, maxVal and count.
Edge cases and common mistakes
- All values negative. For
[-4, -9, -4]the result is[-4, 2]. StartingmaxValat 0 would return 0 with a count of 0, which is not in the slice. - A single element.
[5]gives[5, 1]: the first iteration findsval == maxValand counts it. - Not resetting the count. If a new maximum doesn't set
count = 1, occurrences of smaller values leak into the answer. For[3, 3, 5]the result must be[5, 1]. - Using
>=in the first check. Then an equal value would reset the count to 1 instead of increasing it, and[2, 2]would give[2, 1]. - An empty slice. The solution reads
nums[0], so an empty slice stops the program with an "index out of range" panic. The lesson's inputs always have at least one element; a real caller would checklen(nums)first.
Testing
[2, 7, 11, 8, 11, 8, 3, 11]gives[11, 3].[-4, -9, -4]gives[-4, 2].[5]gives[5, 1].[3, 3, 5]gives[5, 1].