알고리즘/1주일 1문제

2022년 2분기

tsyang 2023. 1. 23. 15:01

프로그래머스 - 사라지는 발판 (lv3)

더보기
#include <string>
#include <vector>

using namespace std;

struct point
{
	point(int x, int y) : x(x), y(y) {}
	int x, y;
};

bool isIn(vector<vector<int>>& board, int x, int y)
{
	return x >= 0 && y >= 0 && x < board.size() && y < board[0].size() && board[x][y] == 1;
}

vector<point> getNearBy(vector<vector<int>>& board, point loc)
{
	vector<point> ret;
	int x, y;

	vector<point> diffs { {0,1}, {0,-1}, {1,0}, {-1,0} };
	for(auto diff : diffs)
	{
		int newX = loc.x + diff.x;
		int newY = loc.y + diff.y;
		if (isIn(board, newX, newY))
			ret.emplace_back(newX, newY);
	}

	return ret;
}


//이기면 true, 지면 false 리턴 / 그리고 걸린 턴수 리턴
pair<bool,int> dfs(vector<vector<int>>& board, point me, point op, int count)	//A점수 , B점수 구분해야할 필요가 ..
{
	auto nearBy = getNearBy(board, me);

	if (nearBy.size() == 0 || board[me.x][me.y] == 0)	//패배, 게임끝	... 내가 진다는건? 
	{
		return make_pair(false, count);
	}
	
	bool result = false;
	int result_count = -1;
	
	for (auto newPos : nearBy)
	{
		board[me.x][me.y] = 0;
		auto opResult = dfs(board, op, newPos, count + 1);
		board[me.x][me.y] = 1;

		bool doIWin = !opResult.first;
		int opCount = opResult.second;

		if(doIWin)	//내가 이겼다.
		{
			if(result == false)	//아직까지 다졌음
			{
				//이긴걸 고름
				result = true;
				result_count = opCount;
			}
			else //이긴적 있으면 더 빠른애 고름
			{
				if (result_count > opCount)
					result_count = opCount;
			}
		}
		else	//내가 졌다.
		{
			if (result == false)	//아직까지 지는거밖에 없음.
			{
				if (result_count < opCount) // 최대한 버틴다.
					result_count = opCount;
			}
		}
	}

	return make_pair(result, result_count);
}

int solution(vector<vector<int>> board, vector<int> aloc, vector<int> bloc) {
	int answer = 0;

	point aPos{ aloc[0], aloc[1] };
	point bPos{ bloc[0], bloc[1] };

	auto result = dfs(board, aPos, bPos, 0);

	answer = result.second;

	return answer;
}

프로그래머스 - 신고 결과 받기

더보기
#include <string>
#include <vector>
#include <unordered_map>
#include <set>

using namespace std;

vector<int> solution(vector<string> id_list, vector<string> report, int k) {
	vector<int> answer;

	unordered_map<string, set<string>> reportMap;
	unordered_map<string, int> counts;
	for (auto& rpt : report)
	{
		auto space = rpt.find(' ');
		auto reporter = rpt.substr(0, space);
		auto reportee = rpt.substr(space, rpt.size() - space);

		auto & reporters = reportMap[reportee];
		reporters.emplace(reporter);
	}

	for(auto value : reportMap)
	{
		auto reporters = value.second;
		if(reporters.size() >= k)	//유저가 정지됨
		{
			for(auto & reporter : reporters)
				counts[reporter]++;
		}
	}

	for(auto id : id_list)
	{
		auto count = counts[id];
		answer.emplace_back(count);
	}
	return answer;
}

백준 13547 - 수열과 쿼리 5 (모스 알고리즘)

더보기
#include <algorithm>
#include <vector>
#include <cmath>
#include <iostream>

using namespace std;


const int MAX_N = 1000000;
int SqrtN;
class Solver
{
public:
	Solver()
	{

	}
	
	void ReadInput(istream& stream)
	{
		stream >> N_;
		SqrtN = sqrt(N_);
		arr_.resize(N_);
		for(int i=0;i< N_;++i)
			stream >> arr_[i];
		stream >> M_;
		queries_.resize(M_);
		for(int i=0;i<M_;++i)
		{
			stream >> queries_[i].s >> queries_[i].e;
			--queries_[i].s;
			queries_[i].idx = i;
		}
		sort(queries_.begin(), queries_.end());
	}

	vector<int> Solve()
	{
		vector<int> result(M_, 0);
		vector<int> cnt(MAX_N +2, 0);
		int numDiff = 0;
		int s = queries_[0].s;
		int e = queries_[0].e;
		
		for (int i = queries_[0].s; i < queries_[0].e; ++i)
			if (cnt[arr_[i]]++ == 0) ++numDiff;
		result[queries_[0].idx] = numDiff;

		for(int i=1; i<M_;++i)
		{
			while (queries_[i].s < s) if (cnt[arr_[--s]]++ == 0) ++numDiff;
			while (e < queries_[i].e) if (cnt[arr_[e++]]++ == 0) ++numDiff;
			while (queries_[i].s > s) if (--cnt[arr_[s++]] == 0) --numDiff;
			while (e > queries_[i].e) if (--cnt[arr_[--e]] == 0) --numDiff;

			result[queries_[i].idx] = numDiff;
		}
		return result;
	}

private:
	struct Query
	{
		int s, e, idx;
		bool operator < (const Query& other) const
		{
			return s / SqrtN != other.s / SqrtN ? s / SqrtN < other.s / SqrtN : e < other.e;
		}
	};
public :
	

private:
	vector<Query> queries_;
	vector<int> arr_;
	int M_;
	int N_;
};

int main()
{
	Solver solver;
	solver.ReadInput(cin);
	auto answer = solver.Solve();
	for (const auto & ans : answer)
		cout << ans << "\n";
	return 0;
}

백준 9202 - Boggle (문자열)

더보기
#include <string>
#include <set>
#include <cstring>
#include <vector>
#include <iostream>
using namespace std;
int dx[] = { 0,0,-1,-1,-1,1,1,1 };
int dy[] = { -1,1,-1,0,1,-1,0,1 };
int score[] = { 0,0,0,1,1,2,3,5,11 };
set<string> answer;
bool visited[4][4];
string boggle[4];

struct Trie {
	bool finish;
	Trie* next[26];
	Trie() : finish(false) {
		memset(next, 0, sizeof(next));
	}
	~Trie() {
		for (int i = 0; i < 26; i++)
			if (next[i] != nullptr)
				delete next[i];
	}
	void insert(string& str) {
		Trie * curNode = this;
		for(int i=0;i<str.size();++i)
		{
			int cur = str[i] - 'A';
			if (curNode->next[cur] == nullptr)
				curNode->next[cur] = new Trie();
			curNode = curNode->next[cur];
		}
		curNode->finish = true;
	}
	
	void query(int i, int j, string cur) {
		if (i < 0 || j < 0 || i >= 4 || j >= 4)return;
		if (visited[i][j])return;
		if (cur.size() >= 8)return;

		visited[i][j] = true;
		cur = cur + boggle[i][j];
		if (next[boggle[i][j] - 'A'] == '\0') {
			visited[i][j] = false;
			return;
		}
		if (next[boggle[i][j] - 'A']->finish)
			answer.insert(cur);
		for (int c = 0; c < 8; c++) {
			next[boggle[i][j] - 'A']->query(i + dx[c], j + dy[c], cur);
		}
		visited[i][j] = false;
	}
};
int main() {
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	int w, b;
	cin >> w;
	Trie *root = new Trie;
	for (int i = 0; i < w; i++) {
		string str;
		cin >> str;
		root->insert(str);
	}
	cin >> b;
	for (int bcnt = 0; bcnt < b; ++bcnt) {
		for (int i = 0; i < 4; ++i) cin >> boggle[i];
		answer.clear();
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				root->query(i, j, "");
			}
		}
		string longstr = *(answer.begin());
		int tscore = 0;
		for (auto ans : answer) {
			if (longstr.size() < ans.size())
				longstr = ans;
			tscore += score[ans.size()];
		}
		cout << tscore << " " << longstr << " " << answer.size() << "\n";
	}
	return 0;
}

리트코드 2 - Add Two Numbers

더보기
class Solution {
public:
	ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
		ListNode * head = new ListNode();
		ListNode * curNode = head;
		int carry = 0;
		while(true)
		{
			if (l1 == nullptr && l2 == nullptr) break;
			int num1 = 0, num2 = 0;

			if (l1 != nullptr)
			{
				num1 = l1->val;
				l1 = l1->next;
			}
			if (l2 != nullptr)
			{
				num2 = l2->val;
				l2 = l2->next;
			}

			int num3 = num1 + num2 + carry;
			if (num3 >= 10)
			{
				carry = 1;
				num3 %= 10;
			}
			else
				carry = 0;

			curNode->next = new ListNode(num3);
			curNode = curNode->next;
		}
		if(carry > 0)
			curNode->next = new ListNode(carry);

		auto answer = head->next;
		delete(head);
		return answer;
	}
};

백준 13418 - 학교 탐방하기 (최소 스패닝 트리)

더보기
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct edge;

int N, M;
vector<edge> edges;

struct edge
{
	edge(int a, int b, int cost) : a(a), b(b), cost(cost) {}
	int a, b, cost;
};

int getRoot(vector<int> & parent, int idx)
{
	if (parent[idx] != idx)
		parent[idx] = getRoot(parent, parent[idx]);
	return parent[idx];
}

bool ascending(const edge& e1, const edge& e2)
{
	return e1.cost < e2.cost;
}

int kruskal(vector<edge> edges)
{
	int totalCost = N;
	int numSelected = 0;

	vector<int> parent(N + 1);
	for (int i = 0; i < N + 1; ++i) parent[i] = i;
	
	for(const auto & e : edges)
	{
		int rootA = getRoot(parent, e.a);
		int rootB = getRoot(parent, e.b);
		if(rootA == rootB)	
			continue;

		totalCost -= e.cost;
		parent[rootA] = rootB;

		if (++numSelected == N)
			return totalCost;
	}

	return totalCost;
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(nullptr);

	cin >> N >> M;

	edges.reserve(M+1);

	for(int i=0;i<M+1;++i)
	{
		int a, b, cost;
		cin >> a >> b >> cost;
		edges.emplace_back(a, b, cost);
	}

	sort(edges.begin(), edges.end(), ascending);	//오름차순으로 정렬 : 오르막길(0) 우선 선택
	int maxVal = kruskal(edges);

	sort(edges.rbegin(), edges.rend(), ascending);	//내림차순 정렬 : 내리막길(1) 우선 선택
	int minVal = kruskal(edges);

	cout << (maxVal * maxVal - minVal * minVal)<<endl;

	return 0;
}

리트코드 4 - Median of Two Sorted Array (Hard)

더보기
int INF = 987654321;
class Solution {
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
	{
		const vector<int>* actualArray = nullptr;//둘 중 하나가 비어있을 경우 사용		
		
		if (nums1.size() == 0)
			actualArray = &nums2;
		else if (nums2.size() == 0)
			actualArray = &nums1;

		if(actualArray != nullptr)	//둘 중 하나가 비어있다.
		{
			int size = actualArray->size();
			if (size % 2 == 0)
				return (actualArray->at(size / 2) + actualArray->at(size / 2 - 1)) / 2.0;
			else
				return actualArray->at(size / 2);
		}
		
		int total = nums1.size() + nums2.size();
		int half = total / 2;
		int L = -1;
		int R = nums1.size();
		double ans = 0;

		while(L<=R)
		{
			int mid = (L + R) / 2;
			int mid2 = half - mid - 2;

			//mid2의 값이 너무 크거나 너무 작은 경우 
			if (mid2 >= (int)nums2.size())
			{
				L = mid + 1;
				continue;
			}
			if(mid2 < - 1)
			{
				R = mid - 1;
				continue;
			}
			
			int maxLeft1 = (mid >= 0) ? nums1[mid] : -INF;
			int minRight1 = (mid + 1 < nums1.size()) ? nums1[mid + 1] : INF;
			int maxLeft2 = (mid2 >= 0) ? nums2[mid2] : -INF;
			int minRight2 = (mid2 + 1 < nums2.size()) ? nums2[mid2 + 1] : INF;

			if(minRight1 < maxLeft2)
			{
				L = mid + 1;
				continue;
			}
			else if(minRight2 < maxLeft1)
			{
				R = mid - 1;
				continue;
			}

			int minRight = minRight1 < minRight2 ? minRight1 : minRight2;
			int maxLeft = maxLeft1 > maxLeft2 ? maxLeft1 : maxLeft2;
			
			if (total % 2 == 0)
				ans = (minRight + maxLeft) / 2.0;
			else
				ans = minRight;
			
			break;
		}

		return ans;
	}
};

프로그래머스 - 금과 은 운반하기 (lv3)

더보기
#include <vector>
using namespace std;

long long solution(int a, int b, vector<int> g, vector<int> s, vector<int> w, vector<int> t) {
	const int size = g.size();
	long long r = static_cast<long long>(1) << 52;
	long long l = 0;
	long long answer = -1;

	while (l <= r)
	{
		const long long mid = (r + l) / 2;
		long long net_gold = 0, net_silver = 0, net_weight = 0;

		for (int i = 0; i < size; ++i)
		{
			long long time = mid;
			long long cnt = 0;
			time -= t[i];
			if (time >= 0)
			{
				++cnt;
				cnt += time / (2 * t[i]);
			}

			const long long max_weight = cnt * w[i];

			net_gold += g[i] < max_weight ? g[i] : max_weight;
			net_silver += s[i] < max_weight ? s[i] : max_weight;
			net_weight += g[i] + s[i] < max_weight ? g[i] + s[i] : max_weight;
		}

		if (net_weight >= a + b
			&& net_gold >= a
			&& net_silver >= b)
		{
			//시간 충분
			answer = mid;
			r = mid - 1;
		}
		else
		{
			//시간 부족
			l = mid + 1;
		}
	}

	return answer;
}

리트코드 3 - Longest Substring Without Repeating Characters (Medium)

더보기
class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		int max = 0;
		int hash[128];
		memset(hash, 0, sizeof(hash));

		int cur = 0;
		int si = 0;
		for(int i=0;i<s.size();)
		{
			if(hash[s[i]] == 0) //중복아님 ..OK
			{
				if (++cur > max) max = cur;
				++hash[s[i]];
				++i;
			}
			else
			{
				--hash[s[si]];
				++si;
				--cur;
			}
		}
		return max;
	}
};

리트코드 - Longest Palindromic Substring (M)

더보기
class Solution {
public:
	string longestPalindrome(string s)
	{
		const int s_len = s.size();
		int maxL = 0, maxLen = 1;

		//홀수
		for(int i=1;i<s_len;++i)
		{
			int halfLen = 1;
			while(i - halfLen >= 0 && i + halfLen < s_len)
			{
				int cur_len = 1 + (halfLen << 1);
				int l = i - halfLen;
				int r = i + halfLen;
				if (s[l] != s[r]) break;
				if(cur_len > maxLen)
				{
					maxL = l;
					maxLen = cur_len;
				}
				++halfLen;
			}
		}

		//짝수
		for(int i=0;i<s_len;++i)
		{
			int halfLen = 1;
			while (i - halfLen + 1 >= 0 && i + halfLen < s_len)
			{
				int cur_len = halfLen << 1;
				int l = i - halfLen + 1;
				int r = i + halfLen;
				if (s[l] != s[r]) break;
				if (cur_len > maxLen)
				{
					maxL = l;
					maxLen = cur_len;
				}
				++halfLen;
			}
		}
		
		return s.substr(maxL, maxLen);
	}
};

리트코드 6 - Zigzag Conversion (M)

더보기
class Solution {
public:
	string convert(string s, int numRows) {
		if (numRows == 1) return s;
		
		const int len = static_cast<int>(s.size());
		string ans = s;	//deep copy

		const int step = numRows * 2 - 2;
		int pos = 0;

		for(int row = 0;row<numRows;++row)
		{
			int cur_idx = row;
			while (cur_idx < len)
			{
				ans[pos++] = s[cur_idx];

				if (row != 0 && row != numRows -1)	//양 끝 제외
				{
					int sub_idx = cur_idx + step - 2*row;
					if (sub_idx < len)
						ans[pos++] = s[sub_idx];
				}
				cur_idx += step;
			}
		}
		return ans;
	}
};

리트코드 7 - Reverse Integer (M)

더보기
class Solution {
public:
	int reverse(int x) {
		int ret = 0;
		int sign = 1;
		
		const int max = 2147483647;
		const int max2 = max / 10;

		if (x < 0)
		{
			if (x == -2147483648) return 0;
			sign = -1;
			x *= -1;
		}

		while (x > 0)
		{
			if (ret > max2) return 0;
			ret *= 10;

			int digit = x % 10;
			if (max - ret < digit) return 0;

			x /= 10;

			ret += digit;
		}

		ret *= sign;

		return ret;
	}
};

리트코드 9 - Palindrome Number (E)

더보기
class Solution {
public:
    bool isPalindrome(int x) {
        
        //음수이거나 끝이 0으로 끝나는 정수는 아님
        if (x < 0 || (x != 0 && x % 10 == 0))
            return false;
        
        //res는 x의 뒷부분 절반을 inverse함
        //x는 앞부분 절반만 남음
        int res = 0;
        while (x > res) {
            res = res * 10 + x % 10;
            x = x / 10;
        }
                
        return (x == res || x == res / 10);
    }
};

 

 

 

 

 

 

'알고리즘 > 1주일 1문제' 카테고리의 다른 글

2022년 4분기  (0) 2023.01.23
2022년 3분기  (0) 2023.01.23
2022년 1분기  (0) 2023.01.23
2021년 4분기  (0) 2022.02.20
2021년 3분기  (0) 2021.10.22