leetcode解題思路分析(二十三)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. 相交鏈表

本題的思路主要是用兩個指針分別指向A/B首部,以同樣速度向後滑動,滑到尾部後指向另一個鏈表再次滑動。如果二者相交且不爲NULL則說明有交點,否則說明不相交。
數學思路主要是:ptrA走了a獨有的+公共部分+b獨有的,而ptrB走了b獨有的+公共部分+a獨有的,速度相同路程相同必定相交。如果交點爲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. 比較版本號
    比較兩個版本號 version1 和 version2。
    如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。

採取兩個隊列讀取比較即可

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
    給定一個已按照升序排列 的有序數組,找到兩個數使得它們相加之和等於目標數。
    函數應該返回這兩個下標值 index1 和 index2,其中 index1 必須小於 index2。
    本題採用暴力搜索可解,但是時間複雜度高。採用哈希表也可以,但是空間複雜度高。最優解法爲採取雙指針滑動。因爲題意說明了是排序數組而且必有唯一解,因此這是最佳解法
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};
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章