Leetcodeの問題解決のアイデアの分析(23)155-167

  1. 最小スタックスタックを
    実現し、一定時間で最小値に戻る

非常に単純な質問です。

class MinStack {
    
    
public:
    /** initialize your data structure here. */
    MinStack() {
    
    }
    
    void push(int x) {
    
    
        if(x < min) {
    
    
            min = x;
        }

        minStack.push(make_pair(min, x));
    }
    
    void pop() {
    
    
        minStack.pop();
        if (minStack.empty()) {
    
    
            min = INT_MAX;
        } else {
    
    
            min = minStack.top().first;
        }
    }
    
    int top() {
    
    
        return minStack.top().second;
    }
    
    int getMin() {
    
    
        return minStack.top().first;
    }

private:
    int min = INT_MAX;
    stack<pair<int, int>> minStack;
};

  1. 交差するリンクリスト

この質問の主な考え方は、2つのポインターを使用してそれぞれA / Bの先頭を指し、同じ速度で後方にスライドし、末尾にスライドした後、もう一方のリンクリストにもう一度スライドすることです。2つが交差していてNULLでない場合は、交差があることを意味します。それ以外の場合は、交差しないことを意味します。
主な数学的な考え方は次のとおりです。ptrAはユニーク+パブリックパーツ+ bユニークを歩き、ptrBはbユニーク+パブリックパーツ+ユニークを歩きます。同じ速度は同じ距離で交差する必要があります。交差がNULLの場合、共通部分は0です

class Solution {
    
    
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    
    
        ListNode *ptrA = headA, *ptrB = headB;
        while (ptrA != ptrB)
        {
    
    
            ptrA = ptrA ? ptrA->next: headB;
            ptrB = ptrB ? ptrB->next: headA;
        }
        return ptrA;      
    }
};
  1. ピークの検出
    ピーク要素は、左右の隣接する値より大きい値を持つ要素を指します。
    入力配列nums(nums [i]≠nums [i + 1])を指定して、ピーク要素を見つけ、そのインデックスを返します。
    配列には複数のピークが含まれる場合がありますが、この場合は、任意のピークの位置を返します。

二分探索を取り、より大きな側にピークがあるはずです

int findPeakElement(int* nums, int numsSize)
{
    
    
    int left = 0;
    int right = numsSize - 1;
    while(left < right)
    {
    
    
        int mid = left + (right - left) / 2;
        if(nums[mid] > nums[mid + 1])
        {
    
    
            right = mid;
        }
        else
        {
    
    
            left = mid + 1;
        }
    }
    return left;
}
  1. 最大間隔
    順序付けられていない配列が与えられた場合、配列がソートされた後、隣接する要素間の最大の差を見つけます。
    配列要素の数が2未満の場合、0を返します。

(1)最も簡単な方法は、stlに付属するソートを呼び出し、次にトラバースして最大値を取得することです。

class Solution 
{
    
    
public:
    int maximumGap(vector<int>& nums)
     {
    
    
        if (nums.size() < 2)
            return 0;

        sort(nums.begin(), nums.end());
        int max = 0;
        for (int i = 1; i < nums.size(); i++)
        {
    
    
            int tmp = nums[i] - nums[i - 1];
            if (tmp > max)
                max = tmp;
        }
        return max;
    }
};

(2)バケットソートで解決

class Solution {
    
    
public:
class Bucket
{
    
    
public:
    bool used = false;
    int minval = numeric_limits<int>::max();        // same as INT_MAX
    int maxval = numeric_limits<int>::min();        // same as INT_MIN
};

int maximumGap(vector<int>& nums)
{
    
    
    if (nums.empty() || nums.size() < 2)
        return 0;

    int mini = *min_element(nums.begin(), nums.end()),
        maxi = *max_element(nums.begin(), nums.end());

    int bucketSize = max(1, (maxi - mini) / ((int)nums.size() - 1));        // bucket size or capacity
    int bucketNum = (maxi - mini) / bucketSize + 1;                         // number of buckets
    vector<Bucket> buckets(bucketNum);

    for (auto&& num : nums) 
    {
    
    
        int bucketIdx = (num - mini) / bucketSize;                          // locating correct bucket
        buckets[bucketIdx].used = true;
        buckets[bucketIdx].minval = min(num, buckets[bucketIdx].minval);
        buckets[bucketIdx].maxval = max(num, buckets[bucketIdx].maxval);
    }

    int prevBucketMax = mini, maxGap = 0;
    for (auto&& bucket : buckets) 
    {
    
    
        if (!bucket.used)
            continue;

        maxGap = max(maxGap, bucket.minval - prevBucketMax);
        prevBucketMax = bucket.maxval;
    }

    return maxGap;
}


};
  1. バージョン番号の
    比較2つのバージョン番号version1とversion2を比較します。
    version1> version2が1を返す場合、version1 <version2が-1を返す場合、それ以外の場合は0を返します。

2つのキューを読み取り、比較する

class Solution {
    
    
public:
    int compareVersion(string version1, string version2) {
    
    
        queue<int> v1, v2;

        //提取数字
        __getQueue(v1, version1);
        __getQueue(v2, version2);       

        //补齐
        if (v1.size() < v2.size())
        {
    
    
            while (v1.size() != v2.size())
                v1.push(0);
        }
        else if (v1.size() > v2.size())
        {
    
    
            while (v1.size() != v2.size())
                v2.push(0);
        }

        //逐个取出,判断大小
        while (!v1.empty())
        {
    
    
            if (v1.front() > v2.front())return 1;
            else if (v1.front() < v2.front()) return-1;
            v1.pop(); v2.pop();
        }
        return 0;
    }

private:
    void __getQueue(queue<int> &q, string s)
    {
    
    
        string tmp;

        for (auto c : s)
        {
    
    
            if (c != '.')
                tmp += c;
            else
            {
    
    
                q.push(stoi(tmp));
                tmp.clear();
            }
        }
        if (tmp != "") 
            q.push(stoi(tmp));

        return;
    }
};
  1. 分数から小数
class Solution {
    
    
public:
    //小数部分如果余数出现两次就表示该小数是循环小数了
    string fractionToDecimal(int numerator, int denominator) {
    
    
        if(denominator==0) return "";//边界条件,分母为0
        if(numerator==0) return "0";//边界条件,分子为0
        string result;
        
        //转换为longlong防止溢出
        long long num = static_cast<long long>(numerator);
        long long denom = static_cast<long long>(denominator);
        
        //处理正负号,一正一负取负号
        if((num>0)^(denom>0))result.push_back('-');
        
        //分子分母全部转换为正数
        num=llabs(num);denom=llabs(denom);
        
        //处理整数部分
        result.append(to_string(num/denom));
        
        //处理小数部分
        num%=denom;                         //获得余数
        if(num==0)return result;             //余数为0,表示整除了,直接返回结果
        result.push_back('.');              //余数不为0,添加小数点
        int index=result.size()-1;          //获得小数点的下标
        unordered_map<int,int> record;      //map用来记录出现重复数的下标,然后将'('插入到重复数前面就好了
        while(num&&record.count(num)==0){
    
       //小数部分:余数不为0且余数还没有出现重复数字
            record[num]=++index;
            num*=10;                        //余数扩大10倍,然后求商,和草稿本上运算方法是一样的
            result+=to_string(num/denom);
            num%=denom;
        }
        if(record.count(num)==1){
    
               //出现循环余数,我们直接在重复数字前面添加'(',字符串末尾添加')'
            result.insert(record[num],"(");
            result.push_back(')');
        }
        return result;
    }
};

  1. 2つの数値の合計2
    昇順で配列された順序付けられた配列が与えられた場合、その合計がターゲットの数値と等しくなるように2つの数値を見つけます。
    関数は2つの添え字値1とindex2を返す必要があります。ここで、index1はindex2より小さい必要があります。
    この質問はブルートフォース検索で解決できますが、時間は非常に複雑です。ハッシュテーブルも使用できますが、スペースの複雑さが非常に高くなります。最適なソリューションは、2ポインタースライドを採用することです。質問の意味は、それがソートされた配列であり、一意のソリューションが必要であることを示しているため、これが最良のソリューションです
class Solution {
    
    
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
    
    
        int low = 0, high = numbers.size() - 1;
        while (low < high) {
    
    
            int sum = numbers[low] + numbers[high];
            if (sum == target)
                return {
    
    low + 1, high + 1};
            else if (sum < target)
                ++low;
            else
                --high;
        }
        return {
    
    -1, -1};
    }
};

おすすめ

転載: blog.csdn.net/u013354486/article/details/105728688