#include <bits/stdc++.h>
using namespace std;
const long long mod = 1000000007;
const unsigned gen_seed =
    std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937_64 gen(gen_seed);
std::vector<std::vector<int> > res;
int get(int x, int y) {
  if (x == y) return 0;
  if (res[x][y] == -1) {
    printf("? %d %d\n", x + 1, y + 1);
    fflush(stdout);
    int ass;
    cin >> ass;
    if (ass == -1) exit(0);
    res[x][y] = ass;
    res[y][x] = ass;
  }
  return res[x][y];
}
int main() {
  int n;
  cin >> n;
  res = std::vector<std::vector<int> >(n, std::vector<int>(n, -1));
  std::vector<int> z(11, -1);
  std::vector<int> d2 = {1};
  for (int u = 0; u < 10; u++) d2.push_back(d2.back() * 2);
  while (1) {
    int a = gen() % n;
    int b = gen() % n;
    while (b == a) b = gen() % n;
    int cur = get(a, b);
    for (int i = 0; i < 11; i++)
      if ((cur & d2[i]) == 0) z[i] = a;
    int good = 1;
    for (int i = 0; i < 11; i++)
      if (z[i] == -1) good = 0;
    if (good) break;
  }
  std::vector<int> ord;
  for (int i = 0; i < n; i++) ord.push_back(i);
  shuffle(ord.begin(), ord.end(), gen);
  map<int, int> pos;
  std::vector<int> ans(n, 0);
  int found0 = 0;
  int found2 = 0;
  for (int i = 0; i < n; i++) {
    int cur = 0;
    for (int j = 0; j < 11; j++) {
      cur += d2[j] & get(ord[i], z[j]);
    }
    ans[ord[i]] = cur;
    pos[cur] = ord[i];
    if (cur == 0) {
      found2 = 1;
      for (int j = 0; j < 11; j++) z[j] = ord[i];
    }
    if (found2 == 0) {
      for (auto x : pos) {
        if ((x.first & cur) == 0) {
          for (int j = 0; j < 11; j++) {
            if ((d2[j] & cur) == 0)
              z[j] = ord[i];
            else
              z[j] = x.second;
          }
          found2 = 1;
          break;
        }
      }
    }
  }
  cout << '!';
  for (auto x : ans) cout << ' ' << x;
  cout << endl;
}
