На самом деле вы можете использовать отладчик для визуализации стековых фреймов при выполнении вашей рекурсии.
Позволяет проанализировать его на простом BST, например:
2
1 3
Начать с корня = 2 (TopStackFrame: {root = 2, k = 3, cnt = 0, val = -1000})
|
root! = null
|
то есть 1 (TopStackFrame: {root = 1, k = 3, cnt = 0, val = -1000})
|
теперь идет слева от 1 (TopStackFrame: {root= null, k = 3, cnt = 0, val = -1000})
|
корень равен нулю, он возвращает val (верхняя часть стека удалена)
|
теперь возвращаются к 1
|
cnt ++ cnt становится 1 (TopStackFrame: {root = 1, k = 3, cnt = 1, val = -1000})
|
cnt! = K идет справа от 1 (TopStackFrame: {root = null, k = 3 cnt = 1, val = -1000})
|
справа от 1 - ноль, возвращает значение val (верхняя часть стека удалена)
|
, а затем снова возвращает значение val (TopStackFrame: {root =1, k = 3, cnt = 1, val = -1000})
|
, теперь 1 готово.
|
теперь вы пришли к 2 (TopStackFrame: {root = 2, k = 3, cnt = 0, val = -1000})
сейчас Вы видите, что значение cnt не 1, а 0, потому что у каждого стекового кадра есть свой собственный набор переменных.
Подобное происходит с переменной val
.
Существует нескольковарианты решения этой проблемы:
a) Вы можете объявить их как переменные-члены в своем классе и обновить их в своей рекурсии, чтобы вам не нужно было возвращать что-либо с помощью вашей рекурсии, просто объявите метод, который ничего не возвращаетно обновляет эти переменные-члены.
b) Вы можете использовать массивы типа int [] val, int [] cnt, каждый из которых содержит один элемент, и обновлять их элементы в каждом рекурсивном вызове.
c) Вы можете использовать итеративный обход по порядку и получить значение, когда число достигает k.
Я бы предпочел 'c'.Это намного чище, не нужно объявлять переменные или массивы членов.Это также предотвращает исключения переполнения стека в сильно несбалансированных деревьях.