데이터 구조 : 삽입, 제거, 포함, 임의 요소 가져 오기, 모두 O (1)


95

인터뷰에서이 문제를 받았습니다. 어떻게 대답하겠습니까?

O (1) 시간에 다음 작업을 제공하는 데이터 구조를 설계합니다.

  • 끼워 넣다
  • 없애다
  • 포함
  • 임의의 요소를 얻다

데이터 종류에 대한 추가 제한을 가정 할 수 있습니까? 같은 더 중복 등이없는
Sanjeevakumar Hiremath

물론 중복되지 않으며 Java 또는 C #과 같은 언어로 내장 된 데이터 구조를 사용할 수도 있습니다.
길드 너 2011

1
/ 정렬되지 않은 주문 : 난 더 사양 재 없다 있습니다
찰스 더피

7
나는이 게시물에 대한 답변을 받았지만 무작위 요소를 얻는 대신 o (1) 무작위 액세스를 제공하기를 원하면 더 합리적입니다.
ramsinb 2013 년

이것에 대한 올바른 해결책을 찾았습니까?
Balaji Boggaram Ramanarayan 2013

답변:


143

해시 테이블 H와 배열 A로 구성된 데이터 구조를 고려하십시오. 해시 테이블 키는 데이터 구조의 요소이고 값은 배열에서의 위치입니다.

  1. insert (value) : 값을 배열에 추가하고 i를 A의 인덱스로 둡니다. H [value] = i로 설정합니다.
  2. remove (value) : A의 값을 포함하는 셀을 A의 마지막 요소로 교체합니다. d를 인덱스 m에있는 배열 A의 마지막 요소로 둡니다. 제거 할 값의 배열에있는 인덱스 인 H [값]이되도록합니다. A [i] = d, H [d] = i를 설정하고 배열의 크기를 1만큼 줄이고 H에서 값을 제거합니다.
  3. contains (값) : H.contains (값) 반환
  4. getRandomElement () : let r = random (A의 현재 크기). 반환 A [r].

배열의 크기가 자동으로 증가해야하기 때문에 요소를 추가하기 위해 O (1)을 분할 할 것입니다.하지만 괜찮다고 생각합니다.


이것은 내가 가진 것과 비슷하지만 요소 자체를 키로 사용하는 것을 놓쳤습니다 .... 나는 내가 가까이 있다는 것을 알았지 만 정말 머리에 못 박혔습니다!
guildner

Google 전화 화면 에서이 질문을 받았으며 동일한 솔루션을 고집 한 후 흥미 롭습니다. 구현을 약간 망 쳤고 두 번째 전화 화면에 할당했습니다.
Andrey Talnikov 2012

배열에 값 추가 : O (1)은 어떻습니까?
Balaji Boggaram Ramanarayan 2013

4
@aamadmi-음, Java에서는 그래야한다고 생각합니다. 의사 코드에서 : 잘 작동합니다 포함
r0u1i

4
왜 배열이 필요한지, 왜 해시 맵을 사용할 수 없습니까?
Ankit Zalani 2014

22

O (1) 조회는 해시 된 데이터 구조를 의미합니다 .

비교 :

  • O (N) 조회로 O (1) 삽입 / 삭제는 연결 목록을 의미합니다.
  • O (1) 삽입, O (N) 삭제 및 O (N) 조회는 배열 지원 목록을 의미합니다.
  • O (logN) 삽입 / 삭제 / 조회는 트리 또는 힙을 의미합니다.

그것은 시작이지만 마지막 요구 사항은 어떻습니까? 해시 된 데이터 구조에서 임의의 요소 (데이터 구조의 각 요소에 대해 동일한 확률)를 얻을 수 있습니까?
길드 너 2011

1
@ lag1980, 나는 당신이 할 수 있다고 생각합니다 :hashtable.get((int)(Math.random()*hashtable.size()));
CMR

3
흠, 그런 요소를 얻을 수있는 해시 테이블이 없습니다. 만약 있다면 이것이 일정한 시간 연산이 될 것이라고 상상할 수 없습니다. 나는 어느 쪽이든 틀린 것으로 입증되고 싶습니다.
길드 너 2011

@ lag1980 ... Clojure의 벡터가 "일정한 시간"인 것과 같은 방식으로 일정한 시간에 쉽게 수행 할 수 있습니다-가능한 가장 큰 log32 () 값이 다음과 같도록 하드웨어에 의해 N의 가능한 값이 제한 될 때 log32 (N) ... 7과 같이 효과적으로 일정한 시간입니다.
Charles Duffy 2012 년

"배열 지원 목록"이란 다음을 의미합니다. 배열?
Hengameh

5

아마도 현명한 솔루션을 찾고 있기 때문에 이것을 좋아하지 않을 수도 있지만 때로는 총을 고수하는 것이 좋습니다 ... 해시 테이블은 이미 요구 사항을 충족합니다 -아마도 다른 어떤 것보다 전반적으로 더 좋습니다 (분명히 상각 상수 시간 및 다른 솔루션에 대한 다른 타협).

까다로운 요구 사항은 "무작위 요소"선택입니다. 해시 테이블에서 이러한 요소를 스캔하거나 조사해야합니다.

폐쇄 형 해싱 / 개방형 주소 지정의 경우 주어진 버킷이 점유 될 가능성은 size() / capacity()이지만 결정적으로 이것은 일반적으로 해시 테이블 구현에 의해 일정한 곱셈 범위로 유지됩니다 (예 : 테이블이 현재 내용보다 예를 들어 1.2 배 더 크게 유지 될 수 있음). 성능 / 메모리 조정에 따라 ~ 10x). 이는 평균적으로 컨테이너의 전체 크기와 완전히 독립적 인 1.2 ~ 10 개의 버킷을 검색 할 수 있음을 의미합니다. 상각 된 O (1).

나는 두 가지 간단한 접근 방식을 상상할 수 있습니다 (그리고 훨씬 더 어리석은 접근 방식).

  • 임의 버킷에서 선형 검색

    • 비어있는 / 가치 보유 버킷을 고려하십시오. "--AC ----- B--D": B를 선호하더라도 첫 번째 "무작위"선택이 공정하다고 말할 수 있습니다 . B는 더 이상 선호 될 가능성이 없기 때문입니다. 그러나 동일한 값을 사용하여 "무작위"선택을 반복하는 경우 B를 반복적으로 선호하는 것은 바람직하지 않을 수 있습니다 (질문에서 확률조차 요구하지 않음).
  • 채워진 버킷을 찾을 때까지 무작위 버킷을 반복적으로 시도하십시오.

    • "only"capacity () / size () 평균 버킷 방문 (위와 같음)-그러나 실제적으로는 난수 생성이 상대적으로 비싸기 때문에 더 비싸고, 무한히 가능성이없는 최악의 행동이라면 무한히 나쁩니다 ...
      • 더 빠른 타협은 무작위로 선택한 초기 버킷에서 미리 생성 된 임의 오프셋 목록을 사용하여 버킷 수에 % -ing하는 것입니다.

훌륭한 솔루션은 아니지만 항상 두 번째 인덱스 배열을 유지 관리하는 메모리 및 성능 오버 헤드보다 전반적으로 더 나은 타협점 일 수 있습니다.


3

가장 좋은 해결책은 아마도 해시 테이블 + 배열 일 것입니다. 정말 빠르고 결정적입니다.

그러나 가장 낮은 등급의 답변 (해시 테이블을 사용하십시오!)도 실제로 훌륭합니다!

  • 재해 싱이 포함 된 해시 테이블 또는 새 버킷 선택 (예 : 버킷 당 하나의 요소, 연결 목록 없음)
  • getRandom ()은 비어있을 때까지 임의의 버킷을 반복적으로 선택하려고합니다.
  • Fail-safe로, 아마도 getRandom (), N (요소 수) 시도 실패 후 [0, N-1]에서 임의의 인덱스 i를 선택한 다음 해시 테이블을 선형으로 살펴보고 # i- 번째 요소를 선택합니다. .

사람들은 "가능한 무한 루프"때문에 이것을 좋아하지 않을 수 있습니다. 그리고 저는 매우 똑똑한 사람들도 이런 반응을 보이는 것을 보았지만 그것은 틀 렸습니다! 무한히 가능성이없는 이벤트 발생 하지 않습니다 .

이 특정 동작에 대해 설정하기 어렵지 않은 의사 랜덤 소스의 좋은 동작과 해시 테이블이 항상 최소 20 % 가득 차 있다고 가정하면 다음을 쉽게 알 수 있습니다.

getRandom ()이 1000 번 이상 시도 하지 않아도 됩니다 . 그냥 결코 . 실제로 그러한 사건의 확률은 0.8 ^ 1000, 즉 10 ^ -97입니다. 그래서 우리는 그것을 10 ^ 88 번 반복해야 10 억분의 1의 기회가 한 번 발생합니다. 이 프로그램이 태양이 죽을 때까지 인류의 모든 컴퓨터에서 풀 타임으로 실행 되더라도 결코 일어나지 않을 것입니다.


1
값이있는 임의의 버킷을 계속 선택하는 경우 무작위 요소를 선택하는 동안 지구상에서 최악의 경우 O (1)로
이어집니다

@ user1147505- "0.8 ^ 1000"번호는 어디서 얻었습니까?
Hengameh

어떻게 도달 했습니까? "해시 테이블이 항상 최소 20 % 가득 차 있습니다."
Hengameh

임의의 버킷을 선택할 수있는 방법을 작성해 주시겠습니까?
헨 게임

3

이 질문에는 두 개의 데이터 구조를 사용합니다.

  • HashMap
  • ArrayList / Array / Double LinkedList.

단계 :-

  1. 삽입 :-X가 이미 HashMap에 있는지 확인하십시오 .-- 시간 복잡도 O (1). 존재하지 않는 경우 ArrayList의 끝에 추가-시간 복잡도 O (1). HashMap에 x를 키로 추가하고 마지막 Index를 값으로 추가하십시오-시간 복잡도 O (1).
  2. 제거 :-X가 HashMap에 있는지 확인-시간 복잡도 O (1). 존재하는 경우 인덱스를 찾아 HashMap-시간 복잡도 O (1)에서 제거하십시오. 이 요소를 ArrayList의 마지막 요소로 바꾸고 마지막 요소 인 시간 복잡도 O (1)를 제거합니다. HashMap-시간 복잡도 O (1)에서 마지막 요소의 색인을 업데이트합니다.
  3. GetRandom :-0부터 ArrayList의 마지막 인덱스까지 난수를 생성합니다. 생성 된 임의 인덱스에서 ArrayList 요소를 반환합니다 .-- 시간 복잡도 O (1).
  4. 검색 :-HashMap에서 x를 키로 참조하십시오. -시간 복잡도 O (1).

코드 :-

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;


public class JavaApplication1 {

    public static void main(String args[]){
       Scanner sc = new Scanner(System.in);
        ArrayList<Integer> al =new ArrayList<Integer>();
        HashMap<Integer,Integer> mp = new HashMap<Integer,Integer>();  
        while(true){
            System.out.println("**menu**");
            System.out.println("1.insert");
            System.out.println("2.remove");
            System.out.println("3.search");
            System.out.println("4.rendom");
            int ch = sc.nextInt();
            switch(ch){
                case 1 : System.out.println("Enter the Element ");
                        int a = sc.nextInt();
                        if(mp.containsKey(a)){
                            System.out.println("Element is already present ");
                        }
                        else{
                            al.add(a);
                            mp.put(a, al.size()-1);

                        }
                        break;
                case 2 : System.out.println("Enter the Element Which u want to remove");
                        a = sc.nextInt();
                        if(mp.containsKey(a)){

                            int size = al.size();
                            int index = mp.get(a);

                            int last = al.get(size-1);
                            Collections.swap(al, index,  size-1);

                            al.remove(size-1);
                            mp.put(last, index);

                            System.out.println("Data Deleted");

                        }
                        else{
                            System.out.println("Data Not found");
                        }
                        break;
                case 3 : System.out.println("Enter the Element to Search");
                        a = sc.nextInt();
                        if(mp.containsKey(a)){
                            System.out.println(mp.get(a));
                        }
                        else{
                            System.out.println("Data Not Found");
                        }
                        break;
                case 4 : Random rm = new Random();
                        int index = rm.nextInt(al.size());
                        System.out.println(al.get(index));
                        break;

            }
        }
    }

}

-시간 복잡도 O (1). -공간 복잡성 O (N).


1

다음은 같은 질문을 받았을 때 잠시 생각해 낸 문제에 대한 C # 솔루션입니다. 다른 표준 .NET 인터페이스와 함께 Add, Remove, Contains 및 Random을 구현합니다. 인터뷰 중에 그렇게 자세하게 구현해야한다는 것은 아니지만 구체적인 해결책을 찾는 것이 좋습니다.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

/// <summary>
/// This class represents an unordered bag of items with the
/// the capability to get a random item.  All operations are O(1).
/// </summary>
/// <typeparam name="T">The type of the item.</typeparam>
public class Bag<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
{
    private Dictionary<T, int> index;
    private List<T> items;
    private Random rand;
    private object syncRoot;

    /// <summary>
    /// Initializes a new instance of the <see cref="Bag&lt;T&gt;"/> class.
    /// </summary>
    public Bag()
        : this(0)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Bag&lt;T&gt;"/> class.
    /// </summary>
    /// <param name="capacity">The capacity.</param>
    public Bag(int capacity)
    {
        this.index = new Dictionary<T, int>(capacity);
        this.items = new List<T>(capacity);
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Bag&lt;T&gt;"/> class.
    /// </summary>
    /// <param name="collection">The collection.</param>
    public Bag(IEnumerable<T> collection)
    {
        this.items = new List<T>(collection);
        this.index = this.items
            .Select((value, index) => new { value, index })
            .ToDictionary(pair => pair.value, pair => pair.index);
    }

    /// <summary>
    /// Get random item from bag.
    /// </summary>
    /// <returns>Random item from bag.</returns>
    /// <exception cref="System.InvalidOperationException">
    /// The bag is empty.
    /// </exception>
    public T Random()
    {
        if (this.items.Count == 0)
        {
            throw new InvalidOperationException();
        }

        if (this.rand == null)
        {
            this.rand = new Random();
        }

        int randomIndex = this.rand.Next(0, this.items.Count);
        return this.items[randomIndex];
    }

    /// <summary>
    /// Adds the specified item.
    /// </summary>
    /// <param name="item">The item.</param>
    public void Add(T item)
    {
        this.index.Add(item, this.items.Count);
        this.items.Add(item);
    }

    /// <summary>
    /// Removes the specified item.
    /// </summary>
    /// <param name="item">The item.</param>
    /// <returns></returns>
    public bool Remove(T item)
    {
        // Replace index of value to remove with last item in values list
        int keyIndex = this.index[item];
        T lastItem = this.items[this.items.Count - 1];
        this.items[keyIndex] = lastItem;

        // Update index in dictionary for last item that was just moved
        this.index[lastItem] = keyIndex;

        // Remove old value
        this.index.Remove(item);
        this.items.RemoveAt(this.items.Count - 1);

        return true;
    }

    /// <inheritdoc />
    public bool Contains(T item)
    {
        return this.index.ContainsKey(item);
    }

    /// <inheritdoc />
    public void Clear()
    {
        this.index.Clear();
        this.items.Clear();
    }

    /// <inheritdoc />
    public int Count
    {
        get { return this.items.Count; }
    }

    /// <inheritdoc />
    public void CopyTo(T[] array, int arrayIndex)
    {
        this.items.CopyTo(array, arrayIndex);
    }

    /// <inheritdoc />
    public bool IsReadOnly
    {
        get { return false; }
    }

    /// <inheritdoc />
    public IEnumerator<T> GetEnumerator()
    {
        foreach (var value in this.items)
        {
            yield return value;
        }
    }

    /// <inheritdoc />
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    /// <inheritdoc />
    public void CopyTo(Array array, int index)
    {
        this.CopyTo(array as T[], index);
    }

    /// <inheritdoc />
    public bool IsSynchronized
    {
        get { return false; }
    }

    /// <inheritdoc />
    public object SyncRoot
    {
        get
        {
            if (this.syncRoot == null)
            {
                Interlocked.CompareExchange<object>(
                    ref this.syncRoot,
                    new object(),
                    null);
            }

            return this.syncRoot;

        }
    }
}

중복 번호가있는 경우 이것이 작동할지 확신 할 수 없습니다.
AlexIIP

@guildner가 질문의 댓글에 중복이 없다고 가정했기 때문에 중복을 처리하지 않습니다. 중복 항목이 추가되면 ArgumentException"같은 키를 가진 항목이 이미 추가되었습니다."라는 메시지가 표시됩니다. (기본 인덱스 사전에서) throw됩니다.
Scott Lerch 2016

1

해싱을 사용하여 Θ (1) 시간에 작업을 지원할 수 있습니다.

insert (x) 1) 해시 맵 조회를 수행하여 x가 이미 있는지 확인합니다. 2) 없으면 배열 끝에 삽입합니다. 3) 해시 테이블도 추가하면 x는 키로 추가되고 마지막 배열 인덱스는 인덱스로 추가됩니다.

remove (x) 1) 해시 맵 조회를 수행하여 x가 있는지 확인합니다. 2) 존재하는 경우 색인을 찾아 해시 맵에서 제거하십시오. 3) 마지막 요소를 배열의이 요소로 바꾸고 마지막 요소를 제거합니다. 마지막 요소는 O (1) 시간에 제거 할 수 있기 때문에 스와핑이 수행됩니다. 4) 해시 맵에서 마지막 요소의 인덱스를 업데이트합니다.

getRandom () 1) 0부터 마지막 ​​인덱스까지 난수를 생성합니다. 2) 무작위로 생성 된 인덱스에 배열 요소를 반환합니다.

search (x) 해시 맵에서 x를 검색합니다.


1

이것은 오래되었지만 C ++에는 답이 없기 때문에 여기에 내 두 센트가 있습니다.

#include <vector>
#include <unordered_map>
#include <stdlib.h>

template <typename T> class bucket{
    int size;
    std::vector<T> v;
    std::unordered_map<T, int> m;
public:
    bucket(){
        size = 0;
        std::vector<T>* v = new std::vector<T>();
        std::unordered_map<T, int>* m = new std::unordered_map<T, int>();
    }
    void insert(const T& item){
        //prevent insertion of duplicates
        if(m.find(item) != m.end()){
            exit(-1);
        }
        v.push_back(item);
        m.emplace(item, size);
        size++;

    }
    void remove(const T& item){
        //exits if the item is not present in the list
        if(m[item] == -1){
            exit(-1);
        }else if(m.find(item) == m.end()){
            exit(-1);
        }

        int idx = m[item];
        m[v.back()] = idx;
        T itm = v[idx];
        v.insert(v.begin()+idx, v.back());
        v.erase(v.begin()+idx+1);
        v.insert(v.begin()+size, itm);
        v.erase(v.begin()+size);
        m[item] = -1;
        v.pop_back();
        size--;

    }

     T& getRandom(){
      int idx = rand()%size;
      return v[idx];

     }

     bool lookup(const T& item){
       if(m.find(item) == m.end()) return false;
       return true;

     }
    //method to check that remove has worked
    void print(){
        for(auto it = v.begin(); it != v.end(); it++){
            std::cout<<*it<<" ";
        }
    }
};

다음은 솔루션을 테스트하기위한 클라이언트 코드입니다.

int main() {

    bucket<char>* b = new bucket<char>();
    b->insert('d');
    b->insert('k');
    b->insert('l');
    b->insert('h');
    b->insert('j');
    b->insert('z');
    b->insert('p');

    std::cout<<b->random()<<std::endl;
    b->print();
    std::cout<<std::endl;
    b->remove('h');
    b->print();

    return 0;
}

0

C # 3.0 + .NET Framework 4에서는 확장 메서드 를 Dictionary<TKey,TValue>사용 하여 요소가 저장된 기본 동적 배열로 인덱싱 할 수 있으므로 제네릭 이 Hashtable보다 훨씬 좋습니다 .System.LinqElementAt()KeyValuePair<TKey,TValue>

using System.Linq;

Random _generator = new Random((int)DateTime.Now.Ticks);

Dictionary<string,object> _elements = new Dictionary<string,object>();

....

Public object GetRandom()
{
     return _elements.ElementAt(_generator.Next(_elements.Count)).Value;
}

그러나 내가 아는 한 Hashtable (또는 그 Dictionary 자손) 은이 문제에 대한 실제 해결책이 아닙니다. ) 동적 크기 조정 경계에서.

이 문제에 대한 실제 해결책이 있습니까? 내가 생각할 수있는 것은 Dictionary / Hashtable 초기 용량을 예상했던 것보다 훨씬 큰 규모로 지정하면 크기를 조정할 필요가 없기 때문에 O (1) 작업을 얻는 것입니다.


해시 테이블에 대해 매우 엄격하다면 O (N) 크기 조정은 피할 수 없습니다. 일부 구현은 크기 조정 비용을 줄이기 위해 타협합니다. 예를 들어 기존 테이블을 유지하면서 두 배의 두 배 크기를 추가하거나 기존 테이블 크기를 제자리에서 조정하려고합니다 (페이지 경계에 가상 주소 공간과 테이블 크기를 신중하게 배치 한 후 복사가 필요하며, 이는 new / malloc mem 대신 메모리 맵이 필요할 수 있습니다. 그런 다음 요소 마이그레이션 논리를 사용하여 더 작은 영역 (보다 밀접하게 수정하여 내부 모델에서)으로 돌아 가기 전에 새로운 더 큰 영역을 찾습니다.
Tony Delroy 2013

0

나는 Anon에 동의합니다. 동일한 공정성을 가진 임의의 요소를 가져와야하는 마지막 요구 사항을 제외하고는 다른 모든 요구 사항은 단일 해시 기반 DS를 사용해서 만 처리 할 수 ​​있습니다. 이를 위해 Java에서 HashSet을 선택하겠습니다. 요소의 해시 코드 모듈로는 O (1) 시간에 기본 배열의 인덱스 번호를 제공합니다. 추가, 제거 및 포함 작업에 사용할 수 있습니다.


0

Java의 HashSet을 사용하여이 작업을 수행 할 수 없습니까? 기본적으로 O (1)에서 insert, del, search를 모두 제공합니다. getRandom의 경우 임의의 동작을 제공하는 Set의 반복자를 사용할 수 있습니다. 나머지 요소에 대해 걱정하지 않고 세트에서 첫 번째 요소를 반복 할 수 있습니다.

public void getRandom(){
    Iterator<integer> sitr = s.iterator();
    Integer x = sitr.next();    
    return x;
}

0
/* Java program to design a data structure that support folloiwng operations
   in Theta(n) time
   a) Insert
   b) Delete
   c) Search
   d) getRandom */
import java.util.*;

// class to represent the required data structure
class MyDS
{
   ArrayList<Integer> arr;   // A resizable array

   // A hash where keys are array elements and vlaues are
   // indexes in arr[]
   HashMap<Integer, Integer>  hash;

   // Constructor (creates arr[] and hash)
   public MyDS()
   {
       arr = new ArrayList<Integer>();
       hash = new HashMap<Integer, Integer>();
   }

   // A Theta(1) function to add an element to MyDS
   // data structure
   void add(int x)
   {
      // If ekement is already present, then noting to do
      if (hash.get(x) != null)
          return;

      // Else put element at the end of arr[]
      int s = arr.size();
      arr.add(x);

      // And put in hash also
      hash.put(x, s);
   }

   // A Theta(1) function to remove an element from MyDS
   // data structure
   void remove(int x)
   {
       // Check if element is present
       Integer index = hash.get(x);
       if (index == null)
          return;

       // If present, then remove element from hash
       hash.remove(x);

       // Swap element with last element so that remove from
       // arr[] can be done in O(1) time
       int size = arr.size();
       Integer last = arr.get(size-1);
       Collections.swap(arr, index,  size-1);

       // Remove last element (This is O(1))
       arr.remove(size-1);

       // Update hash table for new index of last element
       hash.put(last, index);
    }

    // Returns a random element from MyDS
    int getRandom()
    {
       // Find a random index from 0 to size - 1
       Random rand = new Random();  // Choose a different seed
       int index = rand.nextInt(arr.size());

       // Return element at randomly picked index
       return arr.get(index);
    }

    // Returns index of element if element is present, otherwise null
    Integer search(int x)
    {
       return hash.get(x);
    }
}

// Driver class
class Main
{
    public static void main (String[] args)
    {
        MyDS ds = new MyDS();
        ds.add(10);
        ds.add(20);
        ds.add(30);
        ds.add(40);
        System.out.println(ds.search(30));
        ds.remove(20);
        ds.add(50);
        System.out.println(ds.search(50));
        System.out.println(ds.getRandom());`enter code here`
    }
}

-2

무작위 요소를 찾기 위해 epoch % arraysize를 사용하지 않는 이유는 무엇입니까? 배열 크기를 찾는 것은 O (n)이지만 상각 복잡도는 O (1)입니다.


-3

해시 테이블과 함께 이중 링크 목록을 사용할 수 있다고 생각합니다. 키는 요소이고 관련 값은 이중 링크 목록의 노드입니다.

  1. insert (H, E) : 이중 링크 목록에 노드를 삽입하고 H [E] = node로 항목을 만듭니다. O (1)
  2. delete (H, E) : H (E)로 노드 주소를 가져오고이 노드의 이전으로 이동하여 H (E)를 NULL로 삭제하여 O (1)
  3. contains (H, E) 및 getRandom (H)는 분명 O (1)입니다.

이건 말이 안 돼.
innosam 2013-08-23
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.