贪心算法

  1. 分发饼干

贪心策略:给胃口最小的孩子分发尺寸最小的饼干。

int findContentChildren(vector<int>& g, vector<int>& s) {
    std::sort(g.begin(), g.end());
    std::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;
}
  1. 分发糖果

贪心策略:遍历两次,每次遍历时只考虑并更新相邻一侧的大小关系。

int candy(vector<int>& ratings) {
    int size = ratings.size();
    vector<int> count(size, 1);
    for (int i = 1; i < size; ++i) {
        if (ratings[i] > ratings[i - 1]) {
            count[i] = count[i - 1] + 1;
        }
    }
    for (int i = size - 2; i >= 0; --i) {
        if (ratings[i] > ratings[i + 1]) {
            count[i] = max(count[i], count[i + 1] + 1); // 不能破坏已有的关系
        }
    }
    return std::accumulate(count.begin(), count.end(), 0);
}
  1. 无重叠区间

贪心策略:优先保留右端点小且不相交的区间。

int eraseOverlapIntervals(vector<vector<int>>& intervals) {
    // 按右端点从小到大进行排序
    sort(intervals.begin(), intervals.end(),
         [&](const vector<int>& a, const vector<int>& b) {
             return a[1] < b[1];
         });
    int count = 0;
    int end = intervals[0][1];
    for (int i = 1; i < intervals.size(); ++i) {
        if (intervals[i][0] < end)
            count++;
        else
            end = intervals[i][1];
    }
    return count;
}
  1. 种花问题

解法1:修改flower数组

bool canPlaceFlowers(vector<int>& flowerbed, int n) {
    flowerbed.push_back(0); // 为了方便遍历,在前面都加上一个0
    flowerbed.insert(flowerbed.begin(), 0);
    int size = flowerbed.size();
    for (int i = 1; i < size - 1; ++i) {
        if (flowerbed[i - 1] == 0 && flowerbed[i] == 0 &&
            flowerbed[i + 1] == 0) {
            flowerbed[i] = 1;
            n--;
        }
    }
    return n <= 0;
}

解法2:不修改flower数组

bool canPlaceFlowers(vector<int>& flowerbed, int n) {
    int size = flowerbed.size();
    for (int i = 0; i < size; ++i) {
        if ((i == 0 || flowerbed[i - 1] == 0) && flowerbed[i] == 0 &&
            (i == size - 1 || flowerbed[i + 1] == 0)) {
            n--; // 说明flower[i]可以种花
            i++; // 这里没有修改flower[i]的值为1,所以必须跳过下一个,否则遍历下一个元素时会认为前面元素为0
        }
    }
    return n <= 0;
}
  1. 用最少数量的箭引爆气球
> 根据区间左端点进行排序,然后取交集
int findMinArrowShots(vector<vector<int>>& points) {
    int size = points.size();
    sort(points.begin(), points.end(),
         [&](const vector<int>& a, const vector<int>& b) {
             return a[0] < b[0];
         });
    int count = 1;
    vector<int> interval(points[0]);
    for (int i = 1; i < size; ++i) {
        if (points[i][0] <= interval[1]) {              
            interval[1] = min(points[i][1],interval[1]);
        } else {
            interval[1] = points[i][1];
            count++;
        }
        interval[0] = points[i][0];
    }
    return count;
}
  1. 划分字母区间

先记录每个字符最后一次出现的下标,然后在遍历时不断更新当前区间的右端点,如果遍历到了右端点则说明当前区间遍历结束。

vector<int> partitionLabels(string s) {
    vector<int> result;
    vector<int> index(26, -1);
    for (int i = 0; i < s.length(); ++i) {
        index[s[i] - 'a'] = i;
    }
    int start = 0;
    int end = -1;
    for (int i = 0; i < s.length(); ++i) {
        end = max(index[s[i] - 'a'], end);
        if (i == end) {
            result.push_back(i - start + 1);
            start = i + 1;
        }
    }
    return result;
}
  1. 买卖股票的最佳时机 II

贪心策略:只比较前后两天的大小

int maxProfit(vector<int>& prices) {
    int result = 0;
    for (int i = 1; i < prices.size(); ++i) {
        if (prices[i] > prices[i - 1]) {
            result += prices[i] - prices[i - 1];
        }
    }
    return result;
}
  1. 根据身高重建队列

先根据hi从大到小排列,然后根据ki从小到大排列(这个很关键,保证后面插入的元素不会破坏已有的排列),然后依次插入新的集合中

vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
    vector<vector<int>> result;
    sort(people.begin(), people.end(),
         [&](const vector<int>& a, const vector<int>& b) {
             return a[0] != b[0] ? a[0] > b[0] : a[1] < b[1];
         });
    for (auto& x : people) {
        result.insert(result.begin() + x[1], x);
    }
    return result;
}
  1. 非递减数列

贪心策略:每次保证连续3个元素都非递减数列

bool checkPossibility(vector<int>& nums) {
    int count = 0;
    for (int i = 1; i < nums.size() - 1; ++i) {
        if (nums[i - 1] > nums[i]) {
            if (nums[i] > nums[i + 1])
                return false;
            if (nums[i] < nums[i + 1]) {
                count++;
            }
        } else if (nums[i] > nums[i + 1]) {
            if (nums[i - 1] > nums[i + 1]) {
                nums[i + 1] = nums[i];
            } else {
                nums[i] = nums[i + 1];
            }
            count++;
        }
        if (count > 1)
            return false;
    }
    return true;
}
posted @ 2025-07-15 18:34  dengkang1122  阅读(8)  评论(0)    收藏  举报