It’s possible, by an in-place most-significant-bit (base $2$) radix sort.
In the C++ implementation below, there are two relevant functions: sort and helper. In the main sort function, we first separate negative and non-negative numbers with a for loop and then call helper to handle each part.
helper, on the other hand, takes in a range $[a,b)$ to sort and assumes that all numbers in this range have the same bits to the left of the $e$th bit. (At the start, sort sets $e=31$ for negative numbers and $e=30$ for non-negative numbers.) So now we need to separate those numbers with $0$ at the $e$th bit and those with $1$. (For negative numbers, numbers whose absolute values have $1$ at the $e$th bit precede those with $0$.)
This is accomplished by the for loop. The loop invariant is that at the start of each iteration, the range $[a,i)$ has been processed; $[a,m)$ contains the first part (i.e., for non-negative numbers the part whose $e$th bit is $0$), and $[m,i)$ the second part. At the end of the loop we can assume that, in each of the two ranges $[a,m)$ and $[m,b)$, the numbers have the same bits to the left of $(e-1)$th bit (that is, the exponent is down by $1$), and we can further process these two ranges with recursive calls to helper.
DeepSeek-R1 mentioned in-place radix sort when I asked it this question and then I worked out the rest.
#include <bits/stdc++.h>
using namespace std;
void helper(int a, int b, int e, vector<int>& v) {
if (a >= b - 1 || e < 0)
return;
int m = a;
for (int i = a; i < b; i++)
if (v[i] >= 0 && !(v[i] & 1LL << e) ||
v[i] < 0 && -(long long)v[i] & 1LL << e)
swap(v[i], v[m++]);
helper(a, m, e - 1, v);
helper(m, b, e - 1, v);
}
void sort(vector<int>& v) {
int m = 0;
for (int i = 0; i < v.size(); i++)
if (v[i] < 0)
swap(v[i], v[m++]);
helper(0, m, 31, v);
helper(m, v.size(), 30, v);
}
int main() {
vector<int> v = {
-153423, 434, -6232323, -333222444,
23343, -743, -21, 18, 229, 2343, 0,
-2147483648, -2147483647, -2147483646,
2147483647, 2147483646, 2147483645};
sort(v);
for (int i : v)
cout << i << " ";
cout << "\n";
}