Dart: O(1) space by abusing the numerical bounds of the problem
Intuition\nBecause the problem guarantees that input values are $<=10^5$, there are actually only a small number of input values that could start a sequence of 
# Intuition\nBecause the problem guarantees that input values are $<=10^5$, there are actually only a small number of input values that could start a sequence of length 2, of length 3, etc. For example, $317^2 > 10^5$, so we know that any value $>316$ cannot be the first value in a sequence of lenght 2 or more. We extend this to sequences of lengths 3, 4, and 5.\n\nThis allows us to put constant bounds on how many iterations we perform in our main loop.\n\n# Approach\n1. Sort\n2. Iterate through the sorted values, but exit early as soon as we see a value that would be too large to be the start of a sequence longer than the current max.\n3. For each value, binary search to check if the next square exists, then the next, etc.\n\n# Complexity\n- Time complexity: $O(n\\log{n})$ for the sort operation. Main loop is technically $O(\\log{n})$, since the outer loop is bounded at 316 iterations and the inner one is bounded at 5.\n\n- Space complexity: $O(1)$\n\n# Code\n```dart\nclass Solution {\n  int longestSquareStreak(List<int> nums) {\n    var longestStreak = 1;\n    nums.sort();\n    for (var i = 0; i < nums.length && nums[i] <= _maxStartValueByLength[longestStreak+1]!; i++) {\n      if (i > 0 && nums[i] == nums[i-1]) {\n        // Repeat, skip it.\n      }\n      var index = i;\n      var streak = 1;\n      var square = nums[index];\n      while (true) {\n        square *= square;\n        index = binarySearch(nums, square, index + 1);\n        if (index == -1) {\n          break;\n        }\n        streak++;\n        longestStreak = max(longestStreak, streak);\n      }\n    }\n    if (longestStreak == 1) {\n      return -1;\n    }\n    return longestStreak;\n  }\n\n  /// Returns the index of an arbitrary occurrence of [target] in sorted list [list] on or after the [start index].\n  int binarySearch(List<int> list, int target, int start) {\n    var l = start, r = list.length - 1;\n    while (l <= r) {\n      var mid = l + ((r - l) ~/ 2);\n      if (list[mid] == target) {\n        return mid;\n      }\n      if (target < list[mid]) {\n        r = mid - 1;\n      } else {\n        l = mid + 1;\n      }\n    }\n    return -1;\n  }\n\n  static const _maxStartValueByLength = {\n    // sqrt(10^5).floor() = 316 \n    // Any value higher cannot be the first in a sequence of length 2, \n    // because the second value would be out of range\n    2: 316,\n    // (10^5)^(1/4).floor() = 17\n    3: 17,\n    // (10^5)^(1/16).floor = 2\n    4: 2,\n    5: 2,\n    6: 1\n  };\n}\n```
['Dart']