leetcode刷题

这篇博客探讨了多种使用双指针和贪心算法解决数组问题的方法,包括两数之和、合并有序数组、分发饼干、无重叠区间等。每个问题都提供了详细的代码实现,展示了如何通过巧妙地运用这些算法来有效地解决问题,提高时间复杂度和空间复杂度的效率。此外,还涉及了寻找中位数、买卖股票的最佳时机等经典问题的解决方案。
摘要由CSDN通过智能技术生成

记录贴,只为了统一完美格式


双指针

167. 两数之和 II - 输入有序数组

时间复杂度:O(n)
空间复杂度:O(1)

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int l = 0, r = numbers.size()-1;
        while (l < r) {
            int sum = numbers[l] + numbers[r];
            if (sum == target) break;
            if (sum < target) l++;
            else r--;
        }
        return vector<int> {l+1, r+1};
    }
};

88. 合并两个有序数组

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int pos = m + n - 1;
        m--;
        n--;
        while (m >= 0 && n >= 0) {
            if (nums1[m] >= nums2[n]) {
                swap(nums1[pos--], nums1[m--]);
            }
            else {
                swap(nums1[pos--], nums2[n--]);
            }
        }
        while (n>=0) {
            swap(nums1[pos--], nums2[n--]);
        }
    }
};

贪心算法

455.分发饼干

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int i = 0, j = 0;
        while (i<g.size() && j < s.size()) {
            if (g[i] <= s[j]) i++;
            j++;
        }
        return i;
    }
};

135. 分发糖果

class Solution {
public:
    int candy(vector<int>& ratings) {
        if (ratings.size() <= 1) {
            return ratings.size();
        }
        vector<int> res(ratings.size(), 1);
        for (int i = 1; i < ratings.size(); ++i) {
            if (ratings[i] > ratings[i-1]) res[i] = res[i-1] + 1;
        }
        for (int i = ratings.size()-1; i > 0; --i) {
            if (ratings[i] < ratings[i-1]) res[i-1] = max(res[i-1], res[i]+1);
        }
        return accumulate(res.begin(), res.end(), 0);
    }
};

435. 无重叠区间

时间复杂度:O(nlogn)
空间复杂度:O(logn)

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.empty()) {
            return 0;
        }
        // 必须& 不然报超时
        sort(intervals.begin(), intervals.end(), [](const auto &a, const auto &b) {
            return a[1] < b[1];
        });
        int res = 0, right = intervals[0][1], n = intervals.size();
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] < right) ++res;
            else right = intervals[i][1];
        }
        return res;
    }
};

605. 种花问题

自己为空
左边为空 或者 自己是最左
右边为空 或者 自己是最右
时间复杂度:O(m),其中 m 是flowerbed 的长度
空间复杂度:O(1)O(1)。额外使用的空间为常数。

class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        int l = flowerbed.size();
        for (int i = 0; i<flowerbed.size(); i++) {
            if (flowerbed[i] == 0 && (i ==0 || flowerbed[i-1] == 0 ) && (i == l-1 || flowerbed[i+1] == 0 )) {
                n--;
                if (n <= 0) return true;
                flowerbed[i] = 1;
            }
        }
        return n <= 0;
    }
};

452. 用最少数量的箭引爆气球

时间复杂度:O(nlogn)
空间复杂度:O(logn)

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        sort(points.begin(), points.end(), [](vector<int>&a, vector<int>&b) {
            return a[1] < b[1];
        });
        int prev = points[0][1], res = 1;
        for (int i = 1; i < points.size(); i++) {
            if (points[i][0] > prev) {
                res ++;
                prev = points[i][1];
            }
        }
        return res;
    }
};

763. 划分字母区间

时间复杂度:O(n)
空间复杂度:O(26)

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> last_pos(26, 0);
        for (int i = 0; i < s.size(); i++) {
            last_pos[s[i]-'a'] = i;
        }
        int start = 0, end = 0;
        vector<int> res;
        for (int i = 0; i < s.size(); i++) {
            end = max(end, last_pos[s[i] - 'a']);
            if (i == end) {
                res.emplace_back(end-start+1);
                start = end + 1;
            }
        }
        return res;

    }
};

122. 买卖股票的最佳时机 II

时间复杂度:O(n)
空间复杂度:O(1)

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int res = 0;
        for (int i = 0; i < prices.size()-1; i++) {
            res += max(0, prices[i+1] - prices[i]);
        }
        return res;
    }
};

406. 根据身高重建队列

候选从高到低排,然后插空
时间复杂度:O(n^2)
空间复杂度:O(logn)

class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), [](vector<int> &a, vector<int> &b){
            return (a[0] > b[0] || (a[0] == b[0] && a[1] < b[1]));
        });
        vector<vector<int>> res;
        for (auto &p : people) {
            res.insert(res.begin()+p[1], p);
        }
        return res;
    }
};

665. 非递减数列

class Solution {
public:
    bool checkPossibility(vector<int>& nums) {
        if (nums.size() == 1) return true;
        bool flag = nums[0] <= nums[1] ? true:false;
        for (int i = 1; i < nums.size()-1; i++) {
            if (nums[i] > nums[i+1]) {
                if (flag) {
                    if (nums[i+1] >= nums[i-1]) nums[i] = nums[i+1];
                    else nums[i+1] = nums[i];
                    flag = false;
                }
                else return false;
            }
        }
        return true;
    }
};

随缘刷

1.两数之和

解法:hash表

class Solution {
public:
    vector<int> twoSum(vector<int> &nums, int &target) {
        unordered_map<int,int> hashtabel;
        for (int i = 0; i < nums.size(); ++i) {
            auto it = hashtabel.find(target-nums[i]);
            if (it != hashtabel.end()){
                return {it->second, i};
            }
            hashtabel[nums[i]] = i;
        }
        return {};
    }
};

2.两数相加

解法:链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode * addTwoNumbers(ListNode *l1, ListNode *l2){
        ListNode *head = nullptr, *tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val : 0;
            int n2 = l2 ? l2->val : 0;
            int sum = n1 + n2 + carry;
            if (!head) {
                head = tail = new ListNode(sum%10);
            }
            else {
                tail->next = new ListNode(sum%10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) l1 = l1->next;
            if (l2) l2 = l2->next;
        }
        if (carry > 0) {
            tail->next = new ListNode(carry);
        }
        return head;
    }
};

3.无重复字符的最长子串

解法:滑动窗口
时间复杂度:O(N)
空间复杂度:O(∣Σ∣),其中 Σ 表示字符集(即字符串中可以出现的字符),∣Σ∣ 表示字符集的大小。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_set<char> occor;
        int right = 0, left = 0, max_len = 0;
        while (left < s.size()) {
            while (right < s.size() && !occor.count(s[right])) {
                occor.insert(s[right]);
                right ++;
            }
            max_len = max(max_len, right-left);
            occor.erase(s[left]);
            left ++ ;
        }
        return max_len;
    }
};

4.寻找两个正序数组的中位数

策略:二分法

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int left = (m+n+1) / 2;
        int right = (m+n+2) / 2;
        return (getKth(nums1, 0 ,m-1, nums2, 0, n-1, left) + getKth(nums1, 0 ,m-1, nums2, 0, n-1, right)) / 2;
    }

    double getKth(vector<int> &nums1, int start1, int end1, vector<int> &nums2, int start2, int end2, int k) {
        int len1 = end1 - start1 + 1;
        int len2 = end2 - start2 + 1;
        if (len1 > len2) {
            return getKth(nums2, start2, end2, nums1, start1, end1, k);
        }
        // nums1 is null
        if (len1 == 0) {
            return nums2[start2+k-1];
        }
        if (k==1) {
            return min(nums1[start1], nums2[start2]);
        }
        int i = start1 + min(len1, k/2) - 1;
        int j = start2 + min(len2, k/2) - 1;
        if (nums1[i] <= nums2[j]) {
            return getKth(nums1, i+1, end1, nums2, start2, end2, k-(i-start1+1));
        }
        else {
            return getKth(nums1, start1, end1, nums2, j+1, end2, k-(j-start2+1));
        }
    }
};

4.最长回文子串

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        if (n < 2) {
            return s;
        }
        int max_len = 1;
        int begin = 0;
        vector<vector<int>> dp(n, vector<int>(n));
        // init
        for (int i = 0; i< n; i++) {
            dp[i][i] = true;
        }
        // 递归开始
        for (int lenght = 2; lenght <= n; lenght++) {
            for (int i = 0; i < n; i++) {
                int j = lenght+i-1;
                if (j >= n) break;
                if (s[i] != s[j]) {
                    dp[i][j] = false;
                }
                else {
                    if (j-i<3) {
                        dp[i][j] = true;
                    }
                    else dp[i][j] = dp[i+1][j-1];
                }
                if (dp[i][j] && j-i+1 > max_len) {
                    max_len = j-i+1;
                    begin = i;
                }
            }
        }
        return s.substr(begin, max_len);
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值