KBinsDiscretizer creates wrong bins.

### Describe the bug

`KBinsDiscretizer` gives wrong bins and wrong transformed data, when the inputs contains only 2 distinct values, and `n_bins=3`. It only produces 1 bin, which is not expected.  The warning shows some bins are too small so they are merged.

Note that when setting `n_bins=2`, `KBinsDiscretizer` gives more reasonable bins and correct results. However, from the `bin_edges_`, it seems `n_bins=2` is handled separately.

### My guess about the cause
I think the root cause is inconsistent handling of `-inf` and `+inf` in fitting and transforming. 

In fitting, `-inf` and `+inf` are not considered when removing duplicated bin edges. But in transforming data, the first and last bin edges are replaces with `-inf` and `+inf`. Such differences obviously removes some necessary bins.

Taking the case I mentioned as a example, current implementation deduplicates bin edges from `[-1.0, -1.0, 0.0, 0.0]` to `[-1.0, 0.0]`.  Then in transforming, all real values are actually in one bin, since the bin edges are replaced with `-inf` and `+inf`.

A more reasonable conversion is replacing first and last bin edges with `-inf` and `+inf` in fitting, i.e., `[-inf, -1.0, 0.0, inf]`, then removing duplicated edges, which gives `[-inf, -1.0, 0.0, inf]`. This will give expected results.




### Steps/Code to Reproduce

```
from sklearn.preprocessing import KBinsDiscretizer
X = [[-1], [-1], [ 0], [ 0]]
discretizer = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='quantile')
discretizer.fit(X)

print(discretizer.bin_edges_)
Xt = discretizer.transform(X)
print(Xt)
```

### Expected Results

The last `print` should give 
```
[[0.]
 [0.]
 [1.]
 [1.]]
```
or 

```
[[1.]
 [1.]
 [2.]
 [2.]]
```
. It depends on how to implement it correctly.

### Actual Results

The last `print` gives
```
[[0.]
 [0.]
 [0.]
 [0.]]
```

### Versions

```shell
System:
    python: 3.8.16 (default, Jan 17 2023, 16:42:09)  [Clang 14.0.6 ]
executable: /opt/anaconda3/envs/sklearn/bin/python3
   machine: macOS-10.16-x86_64-i386-64bit

Python dependencies:
      sklearn: 1.2.1
          pip: 22.3.1
   setuptools: 65.6.3
        numpy: 1.24.2
        scipy: 1.10.0
       Cython: None
       pandas: None
   matplotlib: None
       joblib: 1.2.0
threadpoolctl: 3.1.0

Built with OpenMP: True

threadpoolctl info:
       user_api: openmp
   internal_api: openmp
         prefix: libomp
       filepath: /opt/anaconda3/envs/sklearn/lib/python3.8/site-packages/sklearn/.dylibs/libomp.dylib
        version: None
    num_threads: 10

       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: /opt/anaconda3/envs/sklearn/lib/python3.8/site-packages/numpy/.dylibs/libopenblas64_.0.dylib
        version: 0.3.21
threading_layer: pthreads
   architecture: Nehalem
    num_threads: 10

       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: /opt/anaconda3/envs/sklearn/lib/python3.8/site-packages/scipy/.dylibs/libopenblas.0.dylib
        version: 0.3.18
threading_layer: pthreads
   architecture: Nehalem
    num_threads: 10
```
```

COMMENT:
IMO, it's fine, since after binning we will still get 2 values. Maybe there is a better way of handling it. For example `searchsorted` is set to `right` boundaries, wich means maybe we only need to append `+inf` to the end while replacing the min value with `-inf`.

But it seems like a decision for core.

Labels: Bug, Needs Decision, module:preprocessing