I made it too complicated first.. It is really simply if full-tree in-order traversal is allowed.

class Solution { int inx, sofar; // closest bool bleft; // target on left of closest vector<int> nums; void go(TreeNode *p, double target) { if (!p) return; go(p->left, target); nums.push_back(p->val); if (abs(sofar - target) > abs(p->val - target)) { inx = nums.size() - 1; sofar = p->val; bleft = target < p->val; } go(p->right, target); } public: vector<int> closestKValues(TreeNode* root, double target, int k) { sofar = std::numeric_limits<int>::min(); go(root, target); size_t len = nums.size(); int l = bleft ? inx - 1: inx; int r = bleft ? inx : inx + 1; vector<int> ret; while (k--) { if (l < 0) { ret.push_back(nums[r ++]); } else if (r == len) { ret.push_back(nums[l --]); } else { double succ_diff = abs(nums[r] - target); double pred_diff = abs(nums[l] - target); if (succ_diff < pred_diff) ret.push_back(nums[r++]); else ret.push_back(nums[l--]); } } return ret; } };