https://programmers.co.kr/learn/courses/30/lessons/42576

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

정확성 정답 -> 효율성에서 틀림 

#include <string>
#include <vector>

#include<algorithm>
using namespace std;

string solution(vector<string> participant, vector<string> completion) {
    string answer = "";
    sort(participant.begin(),participant.end());
    sort(completion.begin(),completion.end());
    
    int saveHash=0;
   for(int i=0;i<participant.size();i++){

       
       for(int j=0;j<completion.size();j++){
           if(participant[i].compare(completion[j])==0){

              participant[i]=" ";
              completion[j]=" ";
               
               continue;
           }
             }
  }
          
     
    for(int i=0;i<participant.size();i++){
        if( participant[i]!=" "){
    
        answer=participant[i];
           }
    }

    
  
    return answer;
}

2020/04/01 - [C++(Math&알고리즘)] - Hash STL

 

Hash STL

#include unordered_map<자료형,자료형> d; ex) unordered_map<string,int>d; d["leo"]=1; cout<<d["leo"]<<endl; -="">1 d["leo"]=6; cout<<d["leo"]<<endl; -="">6</d["leo"]<<endl;></d["leo"]<<endl;></string,int>

kwaksh2319.tistory.com

이용을 해서 효율성 문제를 해결

#include <string>
#include <vector>
#include<unordered_map>
using namespace std;

string solution(vector<string> participant, vector<string> completion) {
    string answer = "";
    unordered_map<string ,int > key;
    for(auto&i:participant)
        key[i]++;
    
    for(auto&i:completion)
        key[i]--;

    for(auto&i:key){
        if(i.second>0){
            answer=i.first;
            break;
        }
    }
    
    return answer;
}

200816 

지난번과 비슷하게 푼것같다.

 

#include <string>
#include <vector>
#include<unordered_map>
#include<iostream>

using namespace std;

string solution(vector<string> participant, vector<string> completion) {
  string answer = "";  
unordered_map<string,int>part;
    for(int i=0;i<participant.size();i++){
        part[participant[i]]++;
        }
     for(int i=0;i<completion.size();i++){
         
         part[completion[i]]--;
     }
    
    for(int i=0;i<participant.size();i++){
     if( part[participant[i]]==1){
         answer=participant[i];
     }   
    }
    
    return answer;
}

unordered_map은 일반적으로 

문자와 숫자가 같이 혼용될때 사용하기 좋은것같다.

특히나 내가 원하는 string 자료들 비교 할떄 굉장히 유용한것같다. 

 

 

 

 

201007

해시가 키가 같으면 동시에 값이 들어간다는걸 잊지말자 

#include <string>
#include <vector>
#include <string.h>
#include<unordered_map>
#include<cstring>
#include<iostream>
using namespace std;

string solution(vector<string> participant, vector<string> completion) {
    string answer = "";
    unordered_map<string,int>ready;
     unordered_map<string,int>finish;
       for(int i=0;i<participant.size();i++){
            ready[participant[i]] +=1;
       }
    
      
       
    
      for(int i=0;i<completion.size();i++){
           ready[completion[i]] -=1;
      }
  
  
    
    for(int i=0;i<participant.size();i++){
        if(ready[participant[i]]==1){
           answer=participant[i];
            i=participant.size();
        }
   }
     
      
  //  answer="";
    return answer;
    
}

 

#include <unordered_map>

 unordered_map<자료형,자료형> d;
 

ex)

unordered_map<string,int >d;

d["leo"]=1;

cout<<d["leo"]<<endl;
//->1

d["leo"]=6;

cout<<d["leo"]<<endl;
//->6

'프로그래밍언어 > C++' 카테고리의 다른 글

부동 소수점수  (0) 2020.08.28
char, unsigned char,signed char  (0) 2020.08.28
큐 STL queue, priority_queue  (0) 2020.02.19
int to string and string to int  (0) 2020.02.18
<c++>Char to String  (0) 2019.10.11

문제를 잘못 이해 했습니다. 

문제를 천천히 잘 읽도록 하겠습니다.

그런데 문제의도와는 다르지만 비슷하게 단어 별로 압축법을 만들었습니다. 

예를들어

aabbccc

2a2b3c ->7개

abcabcdde

2abcdde->2개

abcdabcdeef

4abcdeef->4개

저는 이런식으로 최대로 압축한 갯수를 구했습니다.

보니까 문제의 의도에서는 압축했을때 문자열이 가장 줄수가 가장 적은 문장을 고르는거였습니다. 

 

200818

 해결함

 

https://programmers.co.kr/learn/courses/30/lessons/60057 

 

코딩테스트 연습 - 문자열 압축 | 프로그래머스

데이터 처리 전문가가 되고 싶은 어피치는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자열에서 같은 값이 연속해서 나타나는 것을 그 문자의 개수와 반복되는 값으로 표현하여 더 짧은 문자열로 줄여서 표현하는 알고리즘을 공부하고 있습니다. 간단한 예로 aabbaccc의 경우 2a2ba3c(문자가 반복되지 않아 한번만 나타난 경우 1은 생략함)와 같이 표현할 수

programmers.co.kr

해결 정답 200818

#include <string>
#include <vector>
#include<iostream>
#include <string.h>
#include <string>
#include<cstring>
using namespace std;
int Divide(string s,int count){
    vector<char>c;
     vector<char>str;
    string delS=s;
    string strm="";
   int confirm=1;
   int nor=s.length()%count;
    int totalNum=0;
   // cout<<nor;
  
    static int tmpCounts=s.length(); 
    for(int i=0;i<s.length();i=i+count){
        
    for(int j=i;j<count+i;j++){
         if(s[j]!='!'||s[j]!=' '){
             
               
               c.push_back(s[j]); //비교 데이터 push
               totalNum++;
         
         }
      
      
      
    }
       // cout<<",";
   for(int j=i;j<count+i;j++){
           if(s[j+count]!='!'||s[j+count]!=' '){
               str.push_back(s[j+count]);// 원본 데이터 push
         }
   
   }
       
        
        
        bool bCheck=false;
        for(int j=0;j<c.size();j++){
        if(c[j]==str[j]){
             bCheck=true;
          }else{
             bCheck=false;
              break;
          }
         }
        
        if(bCheck){
            confirm++;
             
        }else if(!bCheck){
            if(confirm!=1){
             strm+=to_string(confirm);
             
            }
            
            tmpCounts=tmpCounts-c.size(); //현재 나눠준 범위가 넘어갔는지 체크
                                          //ex) 10을 3으로 나누면 1개가 남아서 한번더 3으로 나눌때
                                          // 333 +1  인데 여기서 c size 는 문자열과 관계없이 쓰레기값이 들어감
                                          //그래서 3 3 3 3으로 들어가 마지막 2자리가 쓰레기값이 들어감 
                                          // 이걸 없애기 위해 전체 길이를 구해서 c가 카운팅 될때 제거해서 음수값이 
                                          // 나오면 범위가 넘어간거여서 strm 값 입력시 3 3 3 1 이 들어가도록 +ns값을 넣어준다
          //  cout<<endl;
            //cout<<"c.size()"<<c.size()<<",";
            cout<<"tmpCounts"<<tmpCounts<<",";
          int ns=0;
          if(tmpCounts<0){
              ns=tmpCounts;
          }  
            
          for(int j=0;j<c.size()/confirm+ns;j++){ // confirm비교데이터의 중복데이터를 제거 하기위해 
                                                   //confirm 즉 현재 나눠지는 갯수로 나눠서 
                                                 //넣어줌 현재 c는 비교 데이터를 가지고 잇어서 중복데이터가 잇음
                
                   strm+=c[j];
                  // tmpCounts++;
                        
                  
                    //cout<<c[j];
                  
               }
          //  cout<<",";
        
          
            confirm=1;
           
            str.clear();//비교 원본 끝난 pop
            c.clear();//비교 끝난 pop
        }
     //   cout<<",";
     
    }
    cout<<endl;
  
    for(int i=s.length()-nor;i<s.length();i++){
       // strm=strm+s[i];
        str.clear();//비교 원본 끝난 pop
        c.clear();//비교 끝난 pop
    }
    
    
 
    
       fflush(stdin);
   
       if(strm!=""){
      //   cout<<"strm:"<<strm;  
        //  cout<<endl;
        
    
        
            }
     // cout<<"strm:"<< strm.length(); 
  tmpCounts=s.length();
   return strm.length();
}

int solution(string s) {
    int answer = 0;
    int min=Divide(s,1);
    for(int i=2;i<s.length()/2+1;i++){
       int tmp;
        tmp=Divide(s,i);
        if(tmp<=min){
            min=tmp;
        }
        
    }
    
    answer=min;
    
  //  if(s.length()%2==1)
        //answer=s.length();
    
    return answer;
}

상당히 어려웟다 그래도 일단 리뷰 하려한다 내코드여서 효율성은 좋은지 잘모르겟다

일단 통과는햇으니 천천히 해보자 

 

필자는 기본적으로 이걸 나눠서 생각했다

int min=Divide(s,1);
    for(int i=2;i<s.length()/2+1;i++){
       int tmp;
        tmp=Divide(s,i);
        if(tmp<=min){
            min=tmp;
        }
        
    }

그래서 재귀함수를 이용하였고

 

설명하자면 Divide 함수에 이렇게 나눠서 분배햇다 abcdefg는 예시이다.

for(int i=0;i<s.length();i=i+count)

여기서 count는 내가 나눠준 갯수이다.

즉 한글씩 나누는 거라면 1이 들어가고 두글자씩이면 2가 들어간다. .... 결국 재귀 돌리는 for문의 절반으로 나누는거다

즉 8글자를 나눌때 최종적으로 count는 4로 해서 나누는것 까지한다.

 

여기선 미리 비교해줄 테이터를 뽑는다 즉 내가 맘대로 다루기 편하도록 만들기 위해서 stack 공간에 미리 나눠둔 글자만 따로 저장한다 예를들어 한글자씩이면 count에 따라 한글자 세글자면 카운터는 세번돈다. 

그럼 세글자가 저장된다.

for(int j=i;j<count+i;j++){
         if(s[j]!='!'||s[j]!=' '){
             
               
               c.push_back(s[j]); //비교 데이터 push
               totalNum++;
         
         }
      
      
      
    }
       // cout<<",";
   for(int j=i;j<count+i;j++){
           if(s[j+count]!='!'||s[j+count]!=' '){
               str.push_back(s[j+count]);// 원본 데이터 push
         }
   
   }
       

  bCheck는 문자열 검사하는 bool이다 즉 true면 confim++( 압축된 갯수) 이고 아니면 false로 반환된다. 

즉 한글자씩이면 true false만 가능하지만 만약 세글자면 true,true ,false면 이미 이 세글자의 비교에선 틀린거여서 더이상 for문이 돌지 않고 같지않는 단어로 판단한다. 

더이상 같지 않는단어와 이미 압축된 갯수가 1이상이면 strm+=to_string(confirm);  숫자를 먼저 string 변환하여 넣어준다

 

for문은 글자의 크기이다 즉 세글자면 세번 네글자면 네번이 for문으로 돈다

 

bool bCheck=false;
        for(int j=0;j<c.size();j++){
        if(c[j]==str[j]){
             bCheck=true;
          }else{
             bCheck=false;
              break;
          }
         }
        
        if(bCheck){
            confirm++;
             
        }else if(!bCheck){
            if(confirm!=1){
             strm+=to_string(confirm);
             
            }
            
            tmpCounts=tmpCounts-c.size(); //현재 나눠준 범위가 넘어갔는지 체크
                                          //ex) 10을 3으로 나누면 1개가 남아서 한번더 3으로 나눌때
                                          // 333 +1  인데 여기서 c size 는 문자열과 관계없이 쓰레기값이 들어감
                                          //그래서 3 3 3 3으로 들어가 마지막 2자리가 쓰레기값이 들어감 
                                          // 이걸 없애기 위해 전체 길이를 구해서 c가 카운팅 될때 제거해서 음수값이 
                                          // 나오면 범위가 넘어간거여서 strm 값 입력시 3 3 3 1 이 들어가도록 +ns값을 넣어준다
          //  cout<<endl;
            //cout<<"c.size()"<<c.size()<<",";
            cout<<"tmpCounts"<<tmpCounts<<",";
          int ns=0;
          if(tmpCounts<0){
              ns=tmpCounts;
          }  

 

 

그다음 divide 함수 맨 위에 static int tmpCount=s.length(); 가 있는데 

tmpCounts=tmpCounts-c.size();

해준 이유가 글자수 때문이다 예를들어 10글자를 3글자씩 나눠서 압축할때

3 + 3+ 3+1  하고 한글자가 부족하다 이때 문자열은 관계없이 쓰레기 값이 들어가서 

이를 방지하기위해서 tmpCounts 미리 문자열을 받아서 현재 10 -3 =7 다음 7-3=4 다음  4-3=1 다음 1-3=-2 

이런식으로 음수를 측정합니다.

음수가 나왓으면 문자열을 초과한거로 인지합니다.

 

초과한 ns에 음수 -2를 넣어줍니다.  

원래의  tmpCounts 양수면 ns는 0입니다.

  if(tmpCounts<0){
              ns=tmpCounts;
          }  
            

넣어주 c.size()는 현재 비교 문자 갯수 confirm 압축 갯수입니다. ns는 글자 초과시 현재 길이를 뺴줍니다.

예를들어 1글자 비교만하면되는 3 + 3+ 3+1 맨마지막c.size()는3이고

두글자가 쓰레기값 즉  ex)a, 쓰레기 값  , 쓰레기값 confim 은 당연히 1이고요 그럼 3-2(ns) 1만 나오게 됩니다.

그리고 최종 string strm에 입력 해줍니다.

confim 다시 1로 초기화 str,c도 초기화해줍니다. tmpCounts도 초기화 strm을 길이를 리턴합니다.

 

for(int j=0;j<c.size()/confirm+ns;j++){ // confirm비교데이터의 중복데이터를 제거 하기위해 
                                                   //confirm 즉 현재 나눠지는 갯수로 나눠서 
                                                 //넣어줌 현재 c는 비교 데이터를 가지고 잇어서 중복데이터가 잇음
                
                   strm+=c[j];
                  // tmpCounts++;
                        
                  
                    //cout<<c[j];
                  
               }
          //  cout<<",";
        
          
            confirm=1;
           
            str.clear();//비교 원본 끝난 pop
            c.clear();//비교 끝난 pop
        }
        
        tmpCounts=s.length();
   return strm.length();

여기서 어려웟던점은 쓰레기값들이 들어갈때 처리하는 방법이었습니다. 

 

 

 

201017

 

훨씬 간단하게 해결 하였고 

아이디어는 지난번과 비슷함

깊이 우선 탐색과 정렬 그리고 스택을 조합함 

마지막 예외처리가 좀 중요한데 

문자열 비교이기 때문에 하나도 안들어가는 경우랑 

그리고 문자열이 하나만 들어가는 경우이다. 

이것만 주의하면됨 기본적인 아이디어는 지난번과 비슷함 

단지 좀더 효율적으로 잘짠듯하다 

#include <string>
#include <vector>
#include<iostream>
#include <string.h>
#include<cstring>
#include<algorithm>
using namespace std;

int func(string s,int size,int confirm,string totalStr){
    //cout<<endl;
    if(s.size()<size){
        if(s.size()>0){
            for(int i=0;i<s.size();i++){
            totalStr+=s[i];
                }
        }
     //   cout<<size<<":"<<totalStr;
        return totalStr.length();
    }
    
    string str1="";
     string str2="";
   for(int i=0;i<size;i++){
       str1+=s[i];
   }
    
    for(int i=size;i<s.size();i++){
       str2+=s[i];
   }
   // cout<<str1;
    //cout<<endl;
    //cout<<str2;
    //cout<<endl;
    
    
       
    if(strncmp(str1.c_str(),str2.c_str(),size)==0){
        confirm++;
    }else{
        if(confirm>1){
            totalStr+=to_string(confirm);
        }
        totalStr+=str1;
        confirm=1;
        
    }
         
     
    for(int i=0;i<size;i++){
        s.erase(s.begin());
    }
    
  //
    return func(s,size,confirm,totalStr);
}
int solution(string s) {
    int answer = 0;
    int size=s.size();
    vector<int>saveData;
 //   cout<<size;
    string totalStr="";
    if(s.size()==0){
        return 0;
    }
    if(s.size()==1){
        return 1;
    }
    for(int i=0;i<size/2;i++){
        
        int tmpStr=func(s,i+1,1,totalStr);
        saveData.push_back(tmpStr);
            cout<<endl;
       // cout<<"=======================";
        // cout<<endl;
         //cout<<"=======================";
          //  cout<<endl;
    }
    sort(saveData.begin(),saveData.end());
    //cout<<saveData[0];
    answer=saveData[0];
    
    return answer;
}

 

삼각 함수  :

 

 

삼각함수 항등식 :

 

                   

                 

2019/09/02 - [C++(Math&알고리즘)] - Rotation Matrix

 

Rotation Matrix

이전링크에서는 rotation에 대한 설명이 없어서 이부분에 대해서 정리를 해볼까 합니다. 2019/08/20 - [C++(DirectX)] - C++ W(world) V(view) P(projection) matirx C++ W(world) V(view) P(projection) matirx k..

kwaksh2319.tistory.com

                 

구면 좌표계 :

그림을 보시면서 천천히 따라 가시면 될것 같습니다 .

먼저 OA 직선을 구하려고 할떄 OP의 직선과 파이를 알고 있다면 

$$OA=OP*\cos(\pi/2-\phi)$$

여기서 삼각함수 항등식에 의하면 

$$OA=OP*\sin(\phi)$$

다음은 P의 좌표인 (x,y,z)를 구해보겠습니다.

$$x=OA*\cos(\theta)$$

왜냐하면 삼각형을 떼서 보면

위의 그림과 같다. 그렇다면 코사인세타는

 

$$OX/OA=\cos(\theta)$$

 

이다

 

그래서

$$x=OA*\cos(\theta)$$

$$OX/OA=\cos(\theta)$$

$$OA*OX/OA$$

입니다.

그러면 

$$OX$$

가 남습니다.

즉  x좌표는 

 

$$x=OA*\cos(\theta)$$

 

입니다.

그렇다면

위에서 OA 값은

 

$$OA=OP*\sin(\phi)$$

 

였습니다. 

그걸 변경을 하면 

 

$$x=OA*\cos(\theta)$$

$$x=OP*\sin(\phi)\cos(\theta)$$

 

이런식으로 변경이 됩니다. 

 

다른 좌표들도 마찬가지로 

정리해보면 

x좌표 

$$x=OA*\cos(\theta)$$

$$x=OP*\sin(\phi)\cos(\theta)$$

y좌표는 

$$y=OA*\cos(\pi/2-\theta)$$

$$y=OP*\sin(\phi)*cos(\pi/2-\theta)$$

$$y=OP*\sin(\phi)\sin(\theta)$$

 z 좌표는 

$$z=OP*\sin(\pi/2-\phi)$$

$$z=OP*\cos(\phi)$$

이다.

그렇다면 구의

$$x^2+y^2+z^2=OP^2$$

를 증명하자면 

위에 구한 좌표값을 전부 넣어보니다.

$$x^2+y^2+z^2=OP^2$$

$$x^2+y^2+z^2=(OP*\sin(\phi)\cos(\theta))^2+$$

$$(OP*\sin(\phi)\sin(\theta))^2+(OP*\cos(\phi))^2$$

식을 풀면 

$$(OP^2*\sin(\phi)^2*(\cos(\theta)^2+\sin(\theta)^2)$$

$$+OP^2\cos(\phi))^2$$

$$\cos(\theta)^2+\sin(\theta)^2=1$$

그러므로

$$OP^2*\sin(\phi)^2*1+OP^2\cos(\phi))^2$$

가 됩니다. 

정리하면

$$OP^2*\sin(\phi)^2+OP^2\cos(\phi)^2$$

다시한번 

$$OP^2$$

으로 묶으면

$$OP^2*(\sin(\phi)^2+cos(\phi)^2)$$

됩니다.

그러면 마찬가지로 1이 되므로 

$$OP^2*1$$입니다. 

$$x^2+y^2+z^2=OP^2$$

입니다.

 

그렇다면 각도의 값들은 어떻게 구할까요 

위의 그림의 각도인

$$\theta , \phi$$

구해보겠습니다.

$$\phi=\arccos(z/OP)$$

$$\theta=\arctan(y/x)$$

인데 이를 증명해보이겠습니다.

먼저 

$$z=OP*\cos(\phi)$$

이용하여  구해보겠습니다.

$$z/OP=cos(\phi)$$

$$\arccos(x)=cos (y)$$

$$\phi=acrccos(z/OP)$$

다음에는 

$$\tan \theta=(y/x)$$

$$\arctan (x) =\tan (y)$$

$$\theta=\arctan (y/x)$$

이다

https://programmers.co.kr/learn/courses/30/lessons/43163

 

코딩테스트 연습 - 단어 변환 | 프로그래머스

두 개의 단어 begin, target과 단어의 집합 words가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다. 1. 한 번에 한 개의 알파벳만 바꿀 수 있습니다. 2. words에 있는 단어로만 변환할 수 있습니다. 예를 들어 begin이 hit, target가 cog, words가 [hot,dot,dog,lot,log,cog]라면 hit -> hot -> dot -> dog ->

programmers.co.kr

정답 :

#include <string>
#include <vector>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int dfs(string begin, string target, vector<string> words,int num,int start){
    bool bCheck=false;
      for(int k=0;k<words.size();k++){
         if(target.compare(words[k])==0){
              bCheck=true;
              break;
         }
      }
      if(!bCheck){
           return 0;
      }
     
    
     if(words.size()==num){
         
         return 0;
     }
    
     
     if(begin.compare(target)!=0){
    
          char tmpTarget[target.size()];
          target.copy(tmpTarget,target.size());
         
        for(int k=start;k<words.size();k++){
           
           char tmpBegin[begin.size()+1];
           begin.copy(tmpBegin,begin.size());
           int targetCount=0;
          for(int i=0;i<target.size();i++){
            if(tmpTarget[i]!=tmpBegin[i]){
                   targetCount++;
                  }
            }
            if(targetCount<=1){
                
                begin=target;
                num++;
                return num;
            }
          // cout<<tmpBegin[0];
           char tmpWords[words[start].size()];
           words[start].copy(tmpWords,words[start].size());
           
           
            int checkCount=0;
            for(int i=0;i<words[start].length();i++){
                 if(tmpBegin[i]!=tmpWords[i]){
                      checkCount++;
                 }
             }
            // if(checkCount>1){
            //  return dfs( begin,target,  words, num,next);
             // }else{
             //cout<<checkCount;
             int next=start+1;
             if(checkCount<=1){
                cout<<checkCount;
                begin=words[start];
                cout<<begin<<endl;
             //   cout<<checkCount;
                
               if(begin.compare(target)==0){
         
                  return num;
                }
              
                   return dfs( begin,target,  words, num+1,next);
              }else{
                 // num--;
                 
                   return dfs( begin,target,  words, num,next);
             }
             
               // return dfs( begin,target,  words, num,next);
        
                // }
         }
      }  
        
    
}
int solution(string begin, string target, vector<string> words) {
    int answer = 0;
     int num=0;

    answer=dfs( begin,target,  words, num,0);
    
    
    
    return answer;
}

 

200815

이번에 파라미터 문제로 시간을 낭비를 하였다 

다풀어두고 파라미터를 넘길때 생각이 짧았다

#include <string>
#include <vector>
#include<iostream>
using namespace std;
vector<int>data;
 int ccn;
int  Dfs(string begin, string target, vector<string> words,int answer,int count,int sizes){
 
  
 
    if(begin==target){
       
        data.push_back(answer);
       
        return answer;
    }
    
    if(sizes==count){
        
        return 0;
    }
    
    for(int i=0;i<words.size();i++){
        int wordCount=0;
     
       for(int j=0;j<begin.size();j++){
           if(begin[j]==words[i][j]){
               wordCount++;
           }
       }
        if(wordCount>=begin.size()-1){
            string tmpBegin;
            tmpBegin=words[i];
            vector<string> tmpWord;
            tmpWord=words;
            tmpWord.erase(tmpWord.begin()+i);
            
            
           
            ccn=Dfs( tmpBegin, target,  tmpWord,answer+1, count+1,sizes);
          
            
        }
       
         // 
    }
  

  return ccn;
    
    
    
}

int solution(string begin, string target, vector<string> words) {
    int answer = 0;
    int count=0;
    
    
   answer = Dfs( begin,  target, words,answer,count,words.size()-1 );
    
   for(int i=0;i<data.size();i++){
       if(data[i]<answer){
           answer=data[i];
       }
   }
  
    
    return answer;
}

 

DFS 함수내에 있는 재귀함수 부분에서 

처음에 begin과 word를 그대로 넘겼다

문제는 begin=word[j]로 하여 바뀐 상태인데 

다음 for문이 돌고 있는상태에서 당연히 

바뀐 begin으로 확인하니 hit-> hot으로 바뀐 상태로 for문이 돌아서 원하는 문자들을 비교가 이상해졌다.

그러면 현재 돌고 있는 1번 재귀함수에서 begin이 hot->dot으로 바뀌어 버린다.

ccn=Dfs( begin, target,  Word,answer+1, count+1,sizes);

그래서 tmpBegin을 만들어서 tmpBegin 파라미터를 따로 보내줫다 또한  word는 삭제하면 1번 재귀함수 내에서 삭제가 되어버려 for문이 돌다가 만다 그래서 tmpWord를 하나 만들어줘서 그 파라미터만 따로 보내준다.

ccn=Dfs( tmpBegin, target,  tmpWord,answer+1, count+1,sizes);

논리적인 부분에선 틀리지 않앗고 지난번보다 훨씬 간결하게 코드도 만들었다. 

 

문제는 지난번과 마찬가지지로 파라미터를 입력시 재귀함수의 변화에 대한 이해를 더욱 확실히 해야겟다. 

기초가 중요하다 ! 

 

 

 

201006

이번엔 너비 우선 탐색으로 한번 풀어봤다 

개념은 이렇다 

이런식으로 부모 노드에서 자식 노드가 다음 자식(손자) 노드로 넘어가기전에 미리 현재 자식노드를 전부 검사해준다

#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
using namespace std;
 vector<int>saved;
void func(string begin, string target, vector<string> words,int count,vector<bool>bCheck,int size){
    if(size<=count){
        return;
    }
   // cout<<begin<<",";
    for(int i=0;i<words.size();i++){
       int confirm=0;
        if(begin==target){
          //  cout<<count;
           // cout<<endl;
           saved.push_back(count);
           //  cout<<saved[0];
           i=words.size();
           break;
       }    
        for(int j=0;j<begin.size();j++){
        
            
    if(begin[j]!=words[i][j]){
        confirm++;
        
        }
    }
        if(confirm==1&&bCheck[i]==false){
            bCheck[i]=true;
            
            
            //begin=words[i];
             func(words[i], target,  words,count+1,bCheck,size);
           //  cout<<endl;
             //break;
        } 
        
    }
   
        
   
    
}
int solution(string begin, string target, vector<string> words) {
    int answer = 0;
    vector<bool>bCheck;
    for(int i =0;i<words.size();i++){
        bCheck.push_back(false);
    }

     func(begin, target,  words,0,bCheck,words.size());
   if(saved.size()>0)
   {
       sort(saved.begin(),saved.end());
       return saved[0];
   }
    
    return answer;
}

 

맨처음 부모노드 

  func(begin, target,  words,0,bCheck,words.size());

다음 자식노드들 전부 확인 

 for(int i=0;i<words.size();i++){
       int confirm=0;
        if(begin==target){
           saved.push_back(count);        
           i=words.size();
           break;
       }    
        for(int j=0;j<begin.size();j++){
        
            
    if(begin[j]!=words[i][j]){
        confirm++;
        
        }
    }
        if(confirm==1&&bCheck[i]==false){
            bCheck[i]=true;
           
             func(words[i], target,  words,count+1,bCheck,size);
           
        } 
        
    }

문자비교 1글자만 다른경우에 바꿔 줄수 있음

 for(int j=0;j<begin.size();j++){
        
            
    if(begin[j]!=words[i][j]){
        confirm++;
        
        }
    }
        if(confirm==1&&bCheck[i]==false){
            bCheck[i]=true;
           
             func(words[i], target,  words,count+1,bCheck,size);
           
        } 

 bCheck는 현재 자식노드에서 다음 부모가 될 노드를 체크해줌으로써 다음자식(손자) 노드에 중복 방지를 위해 그래서 

다음 노드로 넘어가기전에 bCheck를 true로 변경해줌 

 

 

 

 

현재 노드가 타겟노드와 동일시된경우 경로들어온 숫자만큼 count해주며 더이상 그 함수는 자식노드로 갈필요가 없으므로 함수 종료 

  if(begin==target){
           saved.push_back(count);        
           i=words.size();
           break;
       }    

 

saved는 모드 target에 도착한 길이를 전부 저장 

 

마지막으로 sort하여 가장 짧은 거리 선택 

  if(saved.size()>0)
   {
       sort(saved.begin(),saved.end());
       return saved[0];
   }

만약 target과 일치하는게 없엇을경우 0으로 리턴 

 

 

https://programmers.co.kr/learn/courses/30/lessons/43165

 

코딩테스트 연습 - 타겟 넘버 | 프로그래머스

n개의 음이 아닌 정수가 있습니다. 이 수를 적절히 더하거나 빼서 타겟 넘버를 만들려고 합니다. 예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들려면 다음 다섯 방법을 쓸 수 있습니다. -1+1+1+1+1 = 3 +1-1+1+1+1 = 3 +1+1-1+1+1 = 3 +1+1+1-1+1 = 3 +1+1+1+1-1 = 3 사용할 수 있는 숫자가 담긴 배열 numbers, 타겟 넘버 target이 매개변수로 주어질 때 숫자를 적절히 더하고 빼서 타겟 넘

programmers.co.kr

정답:

#include <string>
#include <vector>

using namespace std;
int answer=0;
void dfs(vector<int> numbers, int target,int num,int sum,int count){
    
    if(numbers.size()==count){
        if(target==sum){
            answer++;
    }
        return;
    }
    
   
    dfs( numbers,  target, num,sum+numbers[count],count+1);
    
  
   
    dfs( numbers,  target, num,sum-numbers[count],count+1);
    
    }

int solution(vector<int> numbers, int target) {
    
    int count=0;
    int sum=0;
    int num=numbers.size();
     dfs( numbers,  target, num,sum,count);
    return answer;
}

200813

다시 푸는데 기억 안나서 결국 내가 풀엇던걸 다시 봣는데 어떻게 이렇게 생각햇지 하면서 

풀고잇다 비슷하겐 만들었는데 생각을 잘못한것같다.

 

현재 풀고 잇으나 어떻게 접근해야하는지 감이 안옴

#include <string>
#include <vector>
#include<iostream>
using namespace std;

struct Save{
    int num;
    bool bCheck;
};
vector<Save> save;
int count=0;
int Bfs(int index,int dataNum,int sum,int target){
    
    
    if(index>=dataNum){
        cout<<endl;
        if(sum==target){
            return 1;
        }else {
            return 0;
        }
        
        
    }
    
    index=index+1;
    
    if(save[index].bCheck==false){
        save[index].bCheck=true;
        sum+=save[index].num;
        
        cout<<"+"<<save[index].num;
        
        
      count  =count+Bfs(index,dataNum,sum,target);
    }
    
    if(save[index].bCheck==true){
        save[index].bCheck=false;
        sum-=save[index].num;
         
           cout<<"-"<<save[index].num;
         count= count+Bfs(index,dataNum,sum,target);
    }
    
    return count;
    
}
int solution(vector<int> numbers, int target) {
    int answer = 0;
    int sum=0;
    
    for(int i=0;i<numbers.size();i++){
        Save tmpSave;
        tmpSave.num=numbers[i];
        tmpSave.bCheck=false;
        save.push_back(tmpSave);
      
    }
    answer=Bfs(-1,numbers.size(),sum,target);
    
  
    
    return answer;
}

지난번이 훨씬 간단하게 푼것같다 이번껀 잘 못푼데다가 접근도 좀 잘못된것같다.

재귀함수랑 dfs를 사용해야한는데 

파라미터 넘기는 방법에 대한 아이디어가 부족한듯 싶다.

200814

#include <string>
#include <vector>
#include<iostream>
using namespace std;
 int answer = 0;
 
void Dfs(vector<int> numbers, int target,int size,int data,int count){
    
    if(numbers.size()==count){
        if(target==data){
            answer++;
        }
        
        return ;
    }
  
    
  Dfs(numbers, target,size,data+numbers[count],count+1);
      
  Dfs(numbers, target,size,data-numbers[count],count+1);
    
    
    return ;
    
}
int solution(vector<int> numbers, int target) {
   
int count=0;    
 int data=0;  
int size=numbers.size();
 Dfs(numbers, target,size,data, count);
    

    
 return answer;
    
}

 

주의점  함수 파라미터를(맴버 변수)를 넘길때 계산을 함수 파라미터에서 계산해주면 현재 함수에 영향이 가지 않는다

즉 다음 파라미터에 영향이 간다 . 재귀함수 특징중 하나라 볼수 잇는데 이게 생각보다 좀 이해가 어렵다

  Dfs(numbers, target,size,data+numbers[count],count+1);

쉽게 설명하자면 예를 들어 count의 경우에 0이라고 할때 

첫번째 함수내에선 0으로 계산이된다 즉 count+1 을 하게 되면 다음 함수에서 더해진값으로 진행된다.

그렇다면 count++ , ++count 은 왜 안되는가이다. count++이랑 ++count 차이는 당연히 알거라 생각하지만

다시한번 설명드리자면 ++count는 그 라인에서 계산된 상태이고 , count++는 다음 줄에서 계산 된 상태가 된다

그렇다면 필자도 실수했던게  ++count하면되겟지 하고 생각햇다 문제는 내 커다란 착각이엇다

그렇게 되면 일단 이함수내의 count는 +1이 되어버린다.  그렇기 때문에 올바른 형태로 계산되지 않는다.

그러므로 count+1을 해서 현재 함수에는 0으로 count를 유지하고 다음 재귀를 탄 파라미터 count가 1이 되어서 계산되야한다 

기초중에 기초이며 정말 중요한 내용이다.

 

201006 

 

가장 깊이 우선탐색의 기본적인 문제 인것같다.

재귀함수의 이해와 어떻게 동작되는지 이해다.  

#include <string>
#include <vector>
#include<iostream>
using namespace std;
int showCount;
void Dfs(vector<int> numbers, int target,int data,int size,int count){
    if(count>=size){
        if(data==target){
            showCount++;  
        }
        return ;
    }
    
  Dfs(numbers,target,data+numbers[count],size,count+1);
    
     
    
   Dfs(numbers,target,data-numbers[count],size,count+1);

   
}
int solution(vector<int> numbers, int target) {
    int answer = 0;
    showCount=0;
    
   Dfs( numbers, target,0,numbers.size(),0);
    //cout<<endl;
   // cout<<showCount;
    return showCount;
}

이런 식으로 가지 치듯 함수가 움직인다. 

정말 몇번을 공부해도 바로바로 적응하는데 시간이 걸리는듯하다 

 

https://programmers.co.kr/learn/courses/30/lessons/42626

 

코딩테스트 연습 - 더 맵게 | 프로그래머스

매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다. 섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2) Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다. Leo가 가진

programmers.co.kr

정답: 

#include <string>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

int solution(vector<int> scoville, int K) {
    int answer=0;
   priority_queue<int,vector<int>,greater<int>> pri_Q;
    
   for(int i=0;i<scoville.size();i++){
      pri_Q.push(scoville[i]);
   }
   int sum=0;
   while(1){
        
        if(pri_Q.size()==1){
            return -1;
        }
        sum=sum+pri_Q.top();
        pri_Q.pop();
        sum=sum+pri_Q.top()*2;
        pri_Q.pop();
        pri_Q.push(sum);
       
        answer++;
        if(pri_Q.top()>=K){
           return answer; 
           //break;
        }
        sum=0;
    
        
        
    }
   
    

    //return 0;
}

200812

 

#include <string>
#include <vector>
#include <queue>
#include<iostream>
using namespace std;

int solution(vector<int> scoville, int K) {
    
    int answer = 0;
    
    priority_queue<int, vector<int>, greater<int> > pq;
    
    for(int i=0;i<scoville.size();i++){
    pq.push(scoville[i]);
        
    }
    
 int total=0;
    while(1){
        if(pq.size()==1){
        return -1;
     }
        
     total+=pq.top();
      
    pq.pop();
        
    total+=pq.top()*2;
       
    pq.pop();
        

     pq.push(total);
     
      answer++;
    if(pq.top()>=K)
    {
     
    
          return answer; 
        
    }
        
     total=0;
    }
  
    
    return answer;
}

지난번코드랑 별반 차이가 없음 

여기 핵심

queue와 prority_queue를 이용인데

순서에 따라 정렬된다.

트리구조를 이루고 있다.

그리고 큐와 스택과 달리 들어오는 순서가 아닌 숫자의 크기를 비교하여 push하면 그 순서에 맞게 정렬됨

pop하면 트리에 탑에 있는 값이 없어지며 다시 정렬되어 두번째로 정렬에 따른 순서로 나옴 

 priority_queue<int, vector<int>, greater<int> > pq;

greater에 경우에 작은숫자부터 큰순서로 트리형태로 정렬

less에 경우에는 큰숫자부터 작은 순으로 트리형태로 정렬

여기서 힙 정렬인 prority_queue를 사용한 이유는 첫번쨰 숫자와 다음 크기의 두번쨰 숫자의 push pop 관계이기에 priority queue를 사용한것이 효율적이다. 

 

201005 지난번과

 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성

 또 이번에도 이부분을 제대로 잘 못이해해서 조금 헤맷다

즉 모든 음식이다 그렇다면 prority queue는 트리 구조로 되어 잇고 작은순부터 가장 큰순이다 결국 가장 작은 값들이 스코필 지수가 올라가서 prority queue 들어가서 정렬되면 최종적으로 top이 가장 작은 값이므로 prority queue

top값만 검사해주면 모든 음식들이 스코필 지수 k이상이 되는셈이다. 

 

#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
#include <queue>
using namespace std;

int solution(vector<int> scoville, int K) {
    int answer = 0;
    
     priority_queue<int, vector<int>, greater<int> > pq;
    
    for(int i=0;i<scoville.size();i++){
    pq.push(scoville[i]);
    }
    
    
    while(pq.size()>1){
    
     int total=0;
      total+=pq.top();
      
    pq.pop();
        
    total+=pq.top()*2;
       
    pq.pop();
    pq.push(total);
    answer++;
    if(pq.top()>=K){
        
       return answer;
    }
    
   
       
    
    
    }
    return -1;
   
    
    
    
   
    
   
}

 

priority_queue<T, Container, Compare>

ex:

priority_queue<int, vector<int>, greater<int>> priority_Q;

priority_queue<자료형, 컨테이너 , 비교함수> priority_Q;

비교함수:

greater<자료형>
less<자료형>

greater 오름차순 

less 내림차순

push(element) 큐 원소에 추가
pop() 큐에 있는 원소 삭제

empty() 큐가 비었으면 true 아니면 false 반환 
size() 큐사이즈 반환 

top() 큐에 top 원소반환 

 

 

queue<T>

ex:

queue<int> q;

queue<자료형> 

front() 큐 제일 앞에 있는 원소 반환 
back() 큐 제일 뒤에 원소 반환 
push(element) 큐 원소에 추가
pop() 큐에 있는 원소 삭제

empty() 큐가 비었으면 true 아니면 false 반환 
size() 큐사이즈 반환 

 

'프로그래밍언어 > C++' 카테고리의 다른 글

char, unsigned char,signed char  (0) 2020.08.28
Hash STL  (0) 2020.04.01
int to string and string to int  (0) 2020.02.18
<c++>Char to String  (0) 2019.10.11
<c++> string to char  (0) 2019.10.11

+ Recent posts