#include <bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
const int N = 3e3;
int a[N], p[N], ans[N], find1, find2;
int pks[N];
bool flat = 0;
vector<int> QQ;
int f[N][N], cnt;
int ask(int x, int y) {
  if (f[x][y] != -1) return f[x][y];
  cnt++;
  if (cnt > 4269) assert(0);
  printf("? %d %d\n", x, y);
  fflush(stdout);
  scanf("%d", &f[x][y]);
  f[y][x] = f[x][y];
  return f[x][y];
}
const int M = 2e6 + 7;
pair<int, int> zhan[M];
int l, r;
void WOW(int x) {
  int nowx = a[1];
  QQ.clear();
  for (int i = 2; i <= x; i++) nowx &= a[i];
  if (nowx) {
    for (int i = 1; i <= x; i++) QQ.push_back(i);
    return;
  }
  zhan[1] = make_pair(0, (1 << 11) - 1);
  r = 1;
  l = 0;
  while (l < r) {
    pair<int, int> Q = zhan[++l];
    for (int i = x; ((1 << (i - 1)) & Q.first) == 0 && i >= 1; i--) {
      if ((a[i] & Q.second) != Q.second) {
        if ((a[i] & Q.second) == 0) {
          Q.first |= (1 << (i - 1));
          for (int j = 1; j <= x; j++)
            if ((Q.first >> (j - 1)) & 1) QQ.push_back(j);
          return;
        }
        zhan[++r] = make_pair(Q.first | (1 << (i - 1)), Q.second & a[i]);
      }
    }
  }
}
int main() {
  int n;
  srand(time(0));
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) pks[i] = i;
  random_shuffle(pks + 1, pks + 1 + n);
  for (int i = 1; i <= n; i++) a[i] = (1 << 11) - 1;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) f[i][j] = -1;
  for (int i = 1; i <= n; i++) p[i] = i;
  random_shuffle(p + 1, p + 1 + n);
  int Q = 5;
  for (int i = 1; i <= n; i++) {
    if (!flat) {
      for (int j = 0; j < QQ.size(); j++) {
        int X = ask(p[QQ[j]], p[i]);
        a[i] &= X;
        a[QQ[j]] &= X;
      }
      for (int j = 1; j < i; j++)
        for (int k = j + 1; k <= i; k++)
          if ((a[k] & a[j]) == 0) {
            find1 = k, find2 = j;
            flat = 1;
            break;
          }
      WOW(i);
    }
  }
  for (int i = 1; i <= n; i++)
    if (i != find1 && i != find2)
      a[i] = ask(p[find1], p[i]) & ask(p[find2], p[i]);
  for (int i = 1; i <= n; i++)
    for (int j = i + 1; j <= n; j++)
      if ((a[i] & a[j]) == 0 && find1 != i && find1 != j) {
        a[find1] = ask(p[i], p[find1]) & ask(p[j], p[find1]);
        break;
      }
  for (int i = 1; i <= n; i++)
    for (int j = i + 1; j <= n; j++)
      if ((a[i] & a[j]) == 0 && find2 != i && find2 != j) {
        a[find2] = ask(p[i], p[find2]) & ask(p[j], p[find2]);
        break;
      }
  for (int i = 1; i <= n; i++) ans[p[i]] = a[i];
  printf("!");
  for (int i = 1; i <= n; i++) printf(" %d", ans[i]);
  printf("\n");
}
