배열의 아나그램 그룹화

문제:

문자열 배열이 주어지면 아나그램을 함께 그룹화합니다.

예를 들어 다음과 같은 배열이 있습니다.

['eat', 'ate', 'apt', 'pat', 'tea', 'now']

[
  ['eat', 'ate', 'tea'], 
  ['apt', 'pat'], 
  ['now']
]

언뜻보기에 이것은 단순한 비교 문제처럼 보입니다. 순진한 알고리즘은 모든 문자열을 다른 모든 문자열과 비교하여 서로 애너그램 인 경우 동일한 버킷에 넣습니다. 순진한 알고리즘의 복잡성은 무엇입니까? C가 문자열의 평균 길이이고 N이 총 문자열 수인 경우이 알고리즘의 복잡성은 O (CN²)입니다. 이는 모든 문자열 대 문자열 비교가 O (C) 시간으로 수행 될 수 있고 O (N²) 문자열 쌍이 있기 때문입니다.

좀 더 통찰력이 있으면 더 효율적인 해싱 기반 알고리즘을 제공 할 수 있습니다 .

  1. 모든 문자열에 대해 해시 함수를 계산합니다. 해시 함수는 서로의 애너그램 인 문자열이 동일한 해시 함수를 갖는 반면, 서로 애너그램이 아닌 문자열은 다른 해시 함수를 갖도록 신중하게 선택해야합니다 . 해시 함수는 계산하기에 효율적이어야합니다.
  2. 해시 함수를 계산 한 후 unordered_mapwith 해시 함수에 문자열을 키로 삽입합니다 . 해시 함수가 충분히 좋다면, 생성 된 무순 맵에는 애너그램이있는 올바른 버킷이 모두 포함됩니다.

해시 함수 및 소인수 분해

  1. 에서 a까지의 모든 문자에 고유 한 소수를 할당합니다 z. (예 : 처음 26 개의 소수는 a:2, b:3, c:5, d:7,...).
  2. 주어진 문자열 의 소수 분해 를 생성합니다 :
  3. 모든 문자 C₁에 대해 문자열에 나타나는 횟수 X₁를 찾습니다.
  4. P (C₁)를 C₁과 관련된 소수라고합시다. P (C₁) ^ X₁ 계산
  5. 필요한 해시 함수는 모든 문자에 대해 계산 된 이러한 모든 P (C₁) ^ X₁ 수량의 곱이됩니다.

다음은 해시 함수를 사용하여 문자열을 버킷 화하는 간단한 알고리즘입니다.

장점 :

  1. 해시 함수는 계산하기 쉽고 효율적입니다. O(C)시간 이 필요 하고 일정한 공간 이 필요 합니다 (여기서는 C문자열의 문자 수).
  2. 해시 함수는 좋습니다. 수학기본 정리는 소인수 분해가 문자열의 모든 문자의 빈도에만 의존하고 위치가 아니라는 것을 보장합니다. 결과적으로 애너그램은 동일한 해시 함수 값을 갖습니다. 비아나 그램은 다른 해시 값을 갖도록 보장됩니다.
  3. 전체 알고리즘은 O(NC)시간 내에 실행 되며 O(NC)공간을 차지 합니다. 여기서은 N총 문자열 수이며 문자열 C의 평균 크기입니다.
  1. 이 해시 함수의 가장 큰 단점은 정수 오버플로입니다. 대부분의 아키텍처에서 unsigned long long64 비트를 차지합니다. (일부 현대 아키텍처에는 더 많은 비트가 있습니다). 따라서로 표시되는 가장 큰 값 unsigned long long은 약 1.8 * 10¹⁹입니다. 지도에서 가장 큰 소수는 101(문자에 해당 z)입니다. 즉, 문자열의 문자 수가를 초과하는 즉시 10정수 오버플로가 발생할 가능성이 높습니다. 101¹⁰> 1.8 * 10¹⁹.

위에 정의 된 해시 함수는 투명하며 코드를 읽는 사람은 누구나 쉽게 이해할 수 있어야합니다. 이 섹션에서는 해싱 컨테이너 유형에 대한 C ++ 언어 지원을 사용 하고 해시 함수 계산을 표준 라이브러리에 위임합니다. 특히 boost::hash_combine.

다음은 일반적인 아이디어입니다.

  1. 정수 또는 long 대신 26 요소 std::arrayunordered_map. 따라서지도 서명은 std::unordered_map<std::array<int, 26> >, std::vector<std::string> >!
  2. 위의 정의가 작동합니까? 불행히도 배열 유형에는 기본 해시 함수가 정의되어 있지 않으므로 외부에서 보완해야합니다. 자세히 살펴보면 에는 해시 함수로를 std::unordered_map임의로 std::function반환 할 수있는 세 번째 템플릿 인수가 있습니다 size_t.
  3. 올바른 해시 함수와 맵 유형을 정의한 후 맵에 삽입하고 반복하는 것은 위의 함수와 동일합니다.

장점 :

  1. 이전 알고리즘과 달리 자체 해시 함수를 만들 필요가 없습니다. 이것은 문제에 대한 영역 지식이 없거나 기본 정리와 같은 수학적 속성을 알지 못하는 경우 특히 유용합니다.
  2. 이 알고리즘은 이전 알고리즘과 마찬가지로 O(NC)시간 내에 실행되고 O(NC)공간을 차지 합니다. 여기서은 N총 문자열 수이며 문자열 C의 평균 크기입니다.
  1. 여기에있는 해시 함수는 불투명하며 boost::combine작동 방식을 파악하기 위해 정의를 깊이 파헤쳐 야합니다. 해시 충돌도 특성화하기 어렵습니다.

우리는 사용할 수있는 기회가 UnorderedElementsAreAnyOf의 정합 기 GUnit을 . 다음은 시도해 볼 몇 가지 테스트 사례입니다.

  1. 빈 배열
  2. 단일 요소 배열
  3. 애너그램이 아닌 문자열 배열
  4. 모든 애너그램 문자열의 배열
  5. 예제와 같은 복잡한 배열

Suggested posts

좋은 습관을 만들고 유지하는 방법

장기적인 습관을 유지하기위한 생산성 팁

좋은 습관을 만들고 유지하는 방법

두 아이의 엄마가 된 후 일을 끝내기가 더 어려워졌습니다. 나는 한 작업에서 다음 작업으로 뛰어 들었고 하루가 끝날 때까지 아무것도하지 않았을 때 실망했습니다.

양자 컴퓨팅 Pt를위한 프로그래밍. 1 : NumPy

이제 양자 컴퓨팅이면의 물리학을 배우기 시작 했으므로 "이봐, 실제로 양자 컴퓨터를 사용하려면 실제로 양자 장치를 손으로 만들어야합니까?"라고 궁금해 할 것입니다. 답은 양자 컴퓨터를 컴퓨터라고 부르는 이유가 있습니다. 프로그래밍이 가능합니다! 이 시리즈에서는 수학 개념을 시뮬레이션하고 양자 컴퓨터에서 실행하는 소프트웨어를 구축하는 방법을 배우게됩니다. 깨끗하고 현대적이며 라이브러리가 풍부한 언어이기 때문에 Python을 사용하여 코드를 작성할 것입니다.

Related posts

"실용적인 프로그래머"의 5 가지 필수 사항

역대 베스트셀러 코딩 북의 요점

"실용적인 프로그래머"의 5 가지 필수 사항

Pragmatic Programmer는 1999 년에 처음 출판되었으며 이후 역대 최고의 프로그래밍 책으로 선정되었습니다. 저자 Andy Hunt와 David Thomas는 Agile Manifesto의 원저자 중 하나였으며 몇 가지 심각한 자격을 가지고 있습니다.

대규모 GraphQL 쿼리 공격으로부터 보호

공격자가 공개적으로 사용 가능한 GraphQL 인터페이스를 사용하여 사이트를 스크랩하거나 서비스 거부 공격을 실행하는 방법에 대해 알아보십시오. 이들은 4 가지 방법 중 하나로이를 수행 할 수 있습니다. 단일 대형 쿼리를 신중하게 구성하여 실행하고, 관련 데이터를 가져올 수있는 병렬 쿼리를 많이 작성하고, 일괄 요청을 사용하여 많은 쿼리를 연속적으로 실행하고, 마지막으로 많은 요청을 보냅니다.

기술 인터뷰의 사회적 구성 요소

코딩 문제는 스트레스가 많지만 스트레스에 대한 당신의 반응은 당신의 기술적 능력보다 더 크게 말합니다.

기술 인터뷰의 사회적 구성 요소

기술 업계의 직책을 위해 인터뷰 할 때 일반적으로 제안을 고려하기 전에 최소한 3 차례의 인터뷰를 거치게됩니다. 라운드는 일반적으로 다음과 같습니다. 그렇게 생각하면 잘못된 것입니다.

훌륭한 개발자의 3 가지 행동 특성

훌륭한 개발자의 3 가지 행동 특성

훌륭한 개발자를 만드는 비 기술적 인 것들 나는이 기사를 작성하는 것을 한동안 미루고 있습니다. 나는 그것을 작성할 자격이 있다고 생각하지 못했습니다. 오늘은 쓸 때라고 생각했습니다.