관리 메뉴

Partially Committed

[Algorithm] λ°°μ—΄ λ‚΄, νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” μ›μ†Œ 쌍 κ²€μƒ‰ν•˜κΈ° λ³Έλ¬Έ

πŸ”₯ Algorithm || λ¬Έμ œν’€μ΄/PS

[Algorithm] λ°°μ—΄ λ‚΄, νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” μ›μ†Œ 쌍 κ²€μƒ‰ν•˜κΈ°

WonderJay 2022. 10. 22. 23:07
728x90
λ°˜μ‘ν˜•
SMALL

 

  배열이 주어지고, λ°°μ—΄ λ‚΄μ—μ„œ νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” μ›μ†Œ μŒμ„ κ²€μƒ‰ν•˜λŠ” 문제 상황을 ν•΄κ²°ν•˜λŠ” 방법에 λŒ€ν•˜μ—¬ κ³΅λΆ€ν•΄λ³΄μž. κ°€λ Ή, 이런 상황이닀. 

  • μœ ν•œ 길이의 1 - d array κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, 두 μ›μ†Œμ˜ 합이 targetNum 이 λ˜λ„λ‘ ν•˜λŠ” μ›μ†Œ μŒμ„ 찾아라.
  • μ–΄λ– ν•œ μ‘°ν•©μœΌλ‘œλ„ targetNum 을 λ§Œλ“€ 수 μ—†λ‹€λ©΄ empty vector 을 λ°˜ν™˜ν•˜λΌ.
  • 두 μ›μ†Œμ˜ 합이 targetNum 이 λ˜λ„λ‘ ν•˜λŠ” μ›μ†Œ μŒμ€ μœ μΌν•˜λ‹€.

   λ©΄μ ‘μ—μ„œ 이 문제λ₯Ό λ¬Όμ–΄λ΄€λ‹€κ³  κ°€μ •ν•˜κ³ , μ°¨κ·Όμ°¨κ·Ό 논리λ₯Ό μ „κ°œν•΄λ³΄μž. λ¨Όμ €, μ—­μœΌλ‘œ 물어봐야 ν•  것은 μ–΄λŠ μ •λ„μ˜ μ‹œκ°„κ³Ό λ©”λͺ¨λ¦¬λ₯Ό ν—ˆμš©ν•˜λŠ”μ§€, λ‹Ήμ—°ν•œ μ†Œλ¦¬κ² μ§€λ§Œ μ›μ†Œμ˜ νƒ€μž…μ€ integer 인지 그리고 2개의 μ›μ†Œμ— λŒ€ν•΄μ„œ 쑰건을 λ§Œμ‘±ν•˜λ©΄ λ˜λŠ”μ§€, λ°˜ν™˜ν•΄μ•Όν•˜λŠ” vector λ‚΄μ˜ μ›μ†Œμ˜ μ •λ ¬ μƒνƒœλŠ” μ–΄λ–»κ²Œ λ˜μ–΄μ•Ό ν•˜λŠ”μ§€ 등을 μ²΄ν¬ν•΄λ³΄λŠ” 것이 μ’‹κ² λ‹€. μ‹€ν–‰ μ‹œκ°„κ³Ό λ©”λͺ¨λ¦¬μ˜ μ œμ•½μ΄ μ—†λŠ” 상황이라면, κ°„λ‹¨ν•œ 방법뢀터 μ œμ‹œν•΄λ³Ό 수 μžˆκ² λ‹€.

 

  첫 번째 방법은 μ‹œκ°„ νš¨μœ¨μ€ 쒋지 μ•Šμ€ νŽΈμ΄μ§€λ§Œ κ΅¬ν˜„μ΄ κ°„λ‹¨ν•˜κ³ , μ΄ν•΄ν•˜κΈ° 쉽닀.

배열을 2번 μˆœνšŒν•œλ‹€. loop 에 μ‚¬μš©ν•˜λŠ” index λ₯Ό i, j 라고 κ°€μ •ν•˜μž. outer loop index κ°€ i 이고 inner loop index κ°€ j 인 것이닀. 그러면, array[i] 에 λŒ€ν•΄μ„œ μ›ν•˜λŠ” 쑰건을 λ§Œμ‘±ν•˜λŠ” array[j] λ₯Ό κ²€μƒ‰ν•œλ‹€. array[i] 와 array[j] 의 합이 targetNum 이 λœλ‹€λ©΄, {array[i], array[j]} λ₯Ό λ°˜ν™˜ν•œλ‹€. 이 방법은 μ‹œκ°„ λ³΅μž‘λ„κ°€ O(N^2) 이며, 곡간 λ³΅μž‘λ„λŠ” (1) 이닀.

// Two Number Sum Solution 1
// Time complexity : O(N^2)
// Spae complexity : O(N) 
// 배열을 2번 νƒμƒ‰ν•˜μ—¬, 쑰건을 λ§Œμ‘±ν•˜λŠ” pair 을 κ²€μΆœ

#include <vector>

using namespace std;

// time  : O(N^2) 
// Space : O(1)
vector<int> twoNumberSum(vector<int> array, int targetSum) {
  // Write your code here.
  vector<int> ans; int present = 0;
  for(int i = 0 ; i < array.size(); i++){
    present = array[i];
    for(int j = i+1  ; j < array.size(); j++){
      if(present + array[j] == targetSum){
        return {present, array[j]};
      }
    }
  }
  
  return ans;
}

  μœ„ 방법을 보닀 μ΅œμ ν™”ν•  수 μžˆκ² λƒλŠ” μš”κ΅¬κ°€ λ“€μ–΄μ˜¨λ‹€λ©΄, 더 효율적인 μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬μƒν•΄μ„œ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό μ€„μ΄λ˜κ°€ ν˜Ήμ€ 곡간 λ³΅μž‘λ„λ₯Ό 쑰금 ν¬μƒν•΄μ„œ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό μ€„μ΄λŠ” λ°©μ•ˆμ΄ μžˆκ² λ‹€. λ‘˜ 쀑 μ–΄λŠ λ°©ν–₯으둜 μƒκ°ν•˜λ©΄ 될 지 물어보고, 생각을 μ§„ν–‰ν•˜μž. μ–΄λŠ 방법도 상관없닀고 ν•˜λ©΄, 곡간 λ³΅μž‘λ„λ₯Ό ν¬μƒν•΄μ„œ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό μ˜¬λ¦¬λŠ” 것이 보닀 μƒκ°ν•˜κΈ° μ‰¬μš΄ 것 κ°™λ‹€.

 

  두 번째 방법은 hash table 을 μΆ”κ°€μ μœΌλ‘œ μ‚¬μš©ν•΄μ„œ 곡간 λ³΅μž‘λ„λ₯Ό O(N) 으둜 ν¬μƒν•˜λŠ” λŒ€μ‹  μ‹œκ°„ λ³΅μž‘λ„λ₯Ό O(N) 으둜 optimize ν•˜λŠ” 것이닀.

λ¨Όμ €, array λ‚΄μ˜ λͺ¨λ“  μ›μ†Œλ₯Ό hash table 에 insert ν•œλ‹€. 그리고 array λ₯Ό 1번만 μˆœνšŒν•˜λ©΄μ„œ(loop index λŠ” i), array[i] 와 matching 이 되면 μš°λ¦¬κ°€ λ§Œμ‘±μ‹œν‚€κ³ μž ν•˜λŠ” 쑰건을 톡과할 수 μžˆλŠ” μ›μ†Œλ₯Ό hash tabel λ‚΄μ—μ„œ μ°ΎλŠ”λ‹€. μœ„ κ²½μš°μ—λŠ” array[i] + x = targetNum 이 λ˜μ–΄μ•Ό ν•˜λ―€λ‘œ, x = targetNum - array[i] κ°€ hash tabel 내에 μ‘΄μž¬ν•˜λŠ” 지 μ°Ύμ•„μ€€λ‹€. λ§Œμ•½μ— μ‘΄μž¬ν•˜λ©΄ {array[i], targetNum - array[i]} 을 λ°˜ν™˜ν•˜κ³ , μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ { } 을 λ°˜ν™˜ν•œλ‹€.

// Two Number Sum Soltion 2
// hash table 을 μ΄μš©ν•œ 풀이

#include <vector>
#include <unordered_set>
using namespace std;

// time  : O(N) || N is length of array
// Space : O(N)
vector<int> twoNumberSum(vector<int> array, int targetSum) {
  // Write your code here.
  unordered_set<int> s(array.begin(), array.end()); int candidate=0;
  for(auto ele : array){
    candidate = targetSum-ele;
    if(s.find(candidate)!=s.end() && candidate != ele)
      return {ele, targetSum-ele};
  }
  
  return {};
}

 

  μ„Έ 번째 방법은 첫 번째 μ‚¬μš©ν•œ 방법을 μ΅œλŒ€ν•œ μ΅œμ ν™”ν•˜μ—¬ O(NlogN) 의 μ‹œκ°„ λ³΅μž‘λ„μ— , O(1) 의 곡간 λ³΅μž‘λ„λ‘œ ν•΄κ²°ν•˜λŠ” 것이닀. μ²˜μŒμ— μ£Όμ–΄μ§€λŠ” 배열이 λ§Œμ•½ μ •λ ¬λœ μƒνƒœλΌλ©΄, λ°°μ—΄μ˜ 첫 인덱슀λ₯Ό μ˜λ―Έν•˜λŠ” left 와 λ°°μ—΄μ˜ λ§ˆμ§€λ§‰ 인덱슀λ₯Ό μ˜λ―Έν•˜λŠ” right λ₯Ό μ„ μ–Έν•œ λ‹€μŒμ— left 와 right λ₯Ό 적절히 움직여가며 targetNum 을 λ§Œμ‘±ν•˜λŠ” μ›μ†Œ μŒμ„ μ°Ύμ•„λ‚Ό 수 μžˆλ‹€. 이 방법은 읡히 투 포인터 μ•Œκ³ λ¦¬μ¦˜μ΄λΌκ³  μ•Œλ €μ Έ μžˆλ‹€. Quick-sort λ₯Ό κ΅¬ν˜„ν•  λ•Œ μ‚¬μš©ν•œ idea 와 쑰금 λΉ„μŠ·ν•œ λŠλ‚Œμ„ λ°›λŠ”λ‹€. (μ—¬λ‹΄μœΌλ‘œ λ™μΌν•œ ꡬ쑰둜, left, right λ₯Ό κ°±μ‹ ν•  λ•Œ λ§ˆλ‹€ 탐색 λ²”μœ„κ°€ μ ˆλ°˜μ”© μ€„μ–΄λ“€κ²Œ λ§Œλ“€λ©΄ 그게 λ°”λ‘œ λ°”μ΄λ„ˆλ¦¬ μ„œμΉ˜μ΄λ‹€.)

// Two Number Sum solution3
// Two pointers Algorithm

#include <vector>
#include <algorithm>

using namespace std;
// time  : O(NlogN) || N is length of array
// Space : O(1)
vector<int> twoNumberSum(vector<int> array, int targetSum) {
  // Write your code here.
  sort(array.begin(), array.end()); int current = 0;
  int left = 0; int right = array.size()-1;
  while(left<right){
    current = array[left]+array[right];
    if(current == targetSum) return {array[left], array[right]};
    else if(current < targetSum){
      left++;
    }
    else if(current > targetSum){
      right--;
    }
  }
  return {};
}

https://github.com/versatile0010/AlgoExpert

 

728x90
λ°˜μ‘ν˜•
LIST
Comments