// includes {{{
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<tuple>
#include<cmath>
#include<random>
#include<cassert>
// }}}
// #include<bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 2e5;
int n;
int a[N];


/// --- Treap Multiset Library {{{ ///

#include <cstdint>
#include <utility>

template < class Key >
struct TreapMultiset {
public:
  const Key key;

private:
  using u32 = uint_fast32_t;
  using PNN = pair< TreapMultiset *, TreapMultiset * >;
  u32 pri;
  TreapMultiset *l = nullptr, *r = nullptr;
  int sz = 1;
  // call after touch its child
  friend TreapMultiset *prop(TreapMultiset *a) {
    a->sz = size(a->l) + 1 + size(a->r);
    return a;
  }
  /// --- XorShift128 Embeddable {{{ ///

  struct XorShift128Embeddable {
    using result_type = uint_fast32_t;
    static constexpr result_type min() { return 0; }
    static constexpr result_type max() { return 0xFFFFFFFF; }
    result_type x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    XorShift128Embeddable(result_type seed = 0) { z ^= seed; }
    result_type operator()() {
      result_type t = x ^ (x << 11);
      x = y, y = z, z = w;
      return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
    }
  };

  /// }}}--- ///
  u32 nextPriority() {
    static XorShift128Embeddable xs(__LINE__ * 3 + 5);
    return xs();
  }

public:
  TreapMultiset(Key key, u32 pri) : key(key), pri(pri) {}
  TreapMultiset(Key key) : TreapMultiset(key, nextPriority()) {}
  friend TreapMultiset *merge(TreapMultiset *a, TreapMultiset *b) {
    if(a == nullptr) return b;
    if(b == nullptr) return a;
    if(a->pri > b->pri) {
      a->r = merge(a->r, b);
      return prop(a);
    } else {
      b->l = merge(a, b->l);
      return prop(b);
    }
  }
  // lower (-inf, key), [key, inf)
  // upper (-inf, key], (key, inf)
  friend PNN split(TreapMultiset *a, Key key, bool upper) {
    if(a == nullptr) return PNN(nullptr, nullptr);
    TreapMultiset *sl, *sr;
    if(upper ? key < a->key : !(a->key < key)) {
      tie(sl, sr) = split(a->l, key, upper);
      a->l = sr;
      return PNN(sl, prop(a));
    } else {
      tie(sl, sr) = split(a->r, key, upper);
      a->r = sl;
      return PNN(prop(a), sr);
    }
  }
  friend PNN lower_split(TreapMultiset *a, const Key &key) {
    return split(a, key, false);
  }
  friend PNN upper_split(TreapMultiset *a, const Key &key) { return split(a, key, true); }
  friend int size(TreapMultiset *a) { return a == nullptr ? 0 : a->sz; }
  friend void insert(TreapMultiset *&a, Key key) {
    TreapMultiset *sl, *sr;
    tie(sl, sr) = lower_split(a, key);
    a = merge(sl, merge(new TreapMultiset(key), sr));
  }
  friend void erase(TreapMultiset *&a, Key key) {
    TreapMultiset *sl, *sr, *tl, *tr;
    tie(sl, sr) = upper_split(a, key);
    tie(tl, tr) = lower_split(sl, key);
    a = merge(tl, sr);
  }
  friend void erase(TreapMultiset *&a, Key keyL, Key keyR, bool inclusive = false) {
    TreapMultiset *sl, *sr, *tl, *tr;
    tie(sl, sr) = split(a, keyR, inclusive);
    tie(tl, tr) = lower_split(sl, keyL);
    a = merge(tl, sr);
  }
  friend void erase1(TreapMultiset *&a, Key key) {
    if(a == nullptr) return;
    if(key < a->key) {
      erase1(a->l, key);
    } else {
      if(!(a->key < key)) {
        a = merge(a->l, a->r);
        return;
      }
      erase1(a->r, key);
    }
    prop(a);
  }
  friend Key getKth(TreapMultiset *&a, int k) {
    static const struct CannotGetKthOfNullptr {} ex;
    if(a == nullptr) throw ex;
    if(k <= size(a->l)) {
      if(k == size(a->l)) return a->key;
      return getKth(a->l, k);
    } else {
      return getKth(a->r, k - size(a->l) - 1);
    }
  }
  friend int count(TreapMultiset *a, Key key) {
    TreapMultiset *sl, *sr, *tl, *tr;
    tie(sl, sr) = upper_split(a, key);
    tie(tl, tr) = lower_split(sl, key);
    int cnt = size(tr);
    merge(merge(tl, tr), sr);
    return cnt;
  }
  friend int count(TreapMultiset *a, Key keyL, Key keyR, bool inclusive = false) {
    TreapMultiset *sl, *sr, *tl, *tr;
    tie(sl, sr) = split(a, keyR, inclusive);
    tie(tl, tr) = lower_split(sl, keyL);
    int cnt = size(tr);
    merge(merge(tl, tr), sr);
    return cnt;
  }
};

/// }}}--- ///

// TreapMultiset< ll > *ms = nullptr;

using P = pair<int, int>;
using Node = TreapMultiset< P >;

bool check(int k) {
  Node *ms = nullptr;
  for(int i = 1; i < n; i++) {
    Node *x, *y;
    tie(x, y) = lower_split(ms, P(a[i], 1e9));
    ms = x;
    delete y;

    P p;
    if(size(ms) && (p = getKth(ms, size(ms) - 1)).first == a[i]) {
      tie(x, y) = lower_split(ms, p);
      ms = x;
      delete y;
    } else {
      p = P(a[i], 0);
    }

    if(a[i] - a[i-1] < 0) {
      p.second++;
    } else if(a[i] - a[i-1] == 0) {
      p.second++;
    } else {
    }
    while(p.second == k) {
      if(p.first == 1) return 0;
      int c = p.first;
      if(size(ms) && (p = getKth(ms, size(ms) - 1)).first == c - 1) {
        tie(x, y) = lower_split(ms, p);
        ms = x;
        delete y;
      } else {
        p = P(c - 1, 0);
      }
      p.second++;
    }
    insert(ms, p);
  }
  delete ms;
  return 1;
}

int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  cin >> n;
  for(int i = 0; i < n; i++) cin >> a[i];
  int ok = 1000000000, ng = 0;
  while(ok - ng > 1) {
    int mid = (ok + ng) >> 1;
    if(check(mid)) ok = mid;
    else ng = mid;
  }
  cout << ok;
  return 0;
}


Measured memory_bytes: 281216