競技プログラミング問題集 SMU Spring 2023

A. 重複要素の削除

与えられた数列から重複要素を削除し、最初に出現した要素のみを保持するアルゴリズム。

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

using namespace std;

vector<int> removeDuplicates(const vector<int>& nums) {
    unordered_map<int, int> countMap;
    vector<int> result;
    
    for (int num : nums) {
        countMap[num]++;
    }
    
    for (int num : nums) {
        if (countMap[num] == 1) {
            result.push_back(num);
        } else {
            countMap[num]--;
        }
    }
    
    return result;
}

int main() {
    vector<int> input = {1, 2, 3, 2, 4, 1, 5};
    vector<int> output = removeDuplicates(input);
    
    for (int num : output) {
        cout << num << " ";
    }
    return 0;
}

B. 連続文字制限

文字列中の連続する'x'文字が3つ以上出現しないように修正するアルゴリズム。

#include <iostream>
#include <string>

using namespace std;

int countExcessX(const string& s) {
    int count = 0;
    int xCount = 0;
    
    for (char c : s) {
        if (c == 'x') {
            xCount++;
            if (xCount > 2) {
                count++;
            }
        } else {
            xCount = 0;
        }
    }
    
    return count;
}

int main() {
    string input = "xxxtxxxoxx";
    cout << countExcessX(input) << endl;
    return 0;
}

C. 階層検索システム

階層構造データから特定の要素を効率的に検索するアルゴリズム。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void findLocations(const vector<int>& floors, const vector<int>& queries) {
    vector<int> prefix(floors.size() + 1, 0);
    
    for (int i = 1; i <= floors.size(); i++) {
        prefix[i] = prefix[i-1] + floors[i-1];
    }
    
    for (int query : queries) {
        auto it = lower_bound(prefix.begin(), prefix.end(), query);
        int floor = distance(prefix.begin(), it);
        int room = query - *(it - 1);
        cout << floor << " " << room << endl;
    }
}

int main() {
    vector<int> floors = {5, 10, 15};
    vector<int> queries = {7, 12, 20};
    findLocations(floors, queries);
    return 0;
}

D. 等差数列変換

数列を最小操作で等差数列に変換可能か判定するアルゴリズム。

#include <iostream>
#include <vector>
#include <climits>

using namespace std;

int canMakeArithmetic(vector<int>& nums) {
    if (nums.size() <= 2) return 0;
    
    int minOperations = INT_MAX;
    
    for (int d1 = -1; d1 <= 1; d1++) {
        for (int d2 = -1; d2 <= 1; d2++) {
            vector<int> temp = nums;
            temp[0] += d1;
            temp[1] += d2;
            
            int diff = temp[1] - temp[0];
            int operations = abs(d1) + abs(d2);
            
            for (int i = 2; i < temp.size(); i++) {
                int currentDiff = temp[i] - temp[i-1];
                if (currentDiff == diff) continue;
                
                if (currentDiff == diff + 1) {
                    temp[i]--;
                    operations++;
                } else if (currentDiff == diff - 1) {
                    temp[i]++;
                    operations++;
                } else {
                    operations = INT_MAX;
                    break;
                }
            }
            
            minOperations = min(minOperations, operations);
        }
    }
    
    return (minOperations == INT_MAX) ? -1 : minOperations;
}

int main() {
    vector<int> nums = {1, 3, 4, 6};
    cout << canMakeArithmetic(nums) << endl;
    return 0;
}

タグ: C++ アルゴリズム 競技プログラミング データ構造 数学

5月29日 14:24 投稿