hot100双指针

发布于:2025-07-12 ⋅ 阅读:(20) ⋅ 点赞:(0)

第一题:283. 移动零 - 力扣(LeetCode)

方法一:双指针。右指针一直往后移动。当右指针遇到0时,左指针停下。当右指针不为0时,交换两个指针对应位置的值。理由:左指针停下的位置一定是0,右指针不为0时交换,就保证了把非零数换到了前面。

代码如下:

class Solution
{
public:
    void moveZeroes(vector<int>& nums)
    {
        int n = nums.size();
        int left = 0, right = 0;
        while (right < n)
        {
            if (nums[right])
            {
                swap(nums[left], nums[right]);
                left++;
            }
            right++;
        }
    }
};

方法二:依然是双指针,但思路不同。思路:遇到非零数就往前放。放完非零数后往数组后面补0即可。

class Solution
{
public:
    void moveZeroes(vector<int>& nums)
    {
        int left = 0, right = 0;
        int n = nums.size();
        while (right < n)
        {
            if (nums[right])
            {
                nums[left++] = nums[right];
            }
            right++;
        }
        for (int i = left; i < n; i++)
        {
            nums[i] = 0;
        }
    }
};

第二题:11. 盛最多水的容器 - 力扣(LeetCode)

方法:贪心+双指针。左指针从最左端开始,右指针从最右端开始。面积=宽*左右指针对应高度较小的那一个。因此哪个指针对应高度较小,就要移动,这样才有可能遇到更高的高度。

class Solution
{
public:
    int maxArea(vector<int>& height)
    {
        int n = height.size();
        int left = 0, right = n - 1;
        int ans = (right - left) * min(height[left], height[right]);
        while (left < right)
        {
            if (height[left] < height[right]) left++;
            else right--;
            ans = max(ans, (right - left) * min(height[left], height[right]));
        }
        return ans;
    }
};

第三题:15. 三数之和 - 力扣(LeetCode)

方法:双指针。先排序,这样好找。假设三个数对应的位置为first,second,third.那么目标值=-nums[first].右指针从末尾往前,左指针从first+1往后即可。

这题需要注意去重。之所以是nums[first]==nums[first-1],是因为nums[first-1]一定已经被处理过了。second那里同理。

class Solution
{
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        vector<vector<int>>ans;
        int n = nums.size();
        sort(nums.begin(), nums.end());
        if (nums[0] == 0 && nums[n - 1] > 0)
        {
            return {};
        }
        else if (nums[0] == 0 && nums[n - 1] == 0)
        {
            return { {0,0,0} };
        }
        for (int first = 0; first < n - 2; first++)
        {
            //去重a
            if (first > 0 && nums[first] == nums[first - 1]) continue;

            int target = -nums[first];
            int third = n - 1;

            for (int second = first + 1; second < n - 1; second++)
            {
                //去重b
                if (second > first + 1 && nums[second] == nums[second - 1]) continue;

                while (second<third && nums[second] + nums[third]>target) third--;
                if (second == third) break;//对于a来说找不到b+c+=-a,first指针后移
                if (nums[second] + nums[third] == target)
                {
                    ans.push_back({ nums[first],nums[second],nums[third] });
                }
            }
        }
        return ans;
    }
};

第四题:42. 接雨水 - 力扣(LeetCode)

方法:dp。这题也可以使用双指针,但是dp更好理解,不过空间复杂度是O(n),双指针是O(1)。

对于下标i,它所能装的水的高度=它左边最高柱子高度与它右边最高柱子高度当中较小的那一个。所以对于每个下标i,我们只需要统计出其左边最高柱子高度和右边最高柱子高度。直接枚举的话复杂度为O(n^2),采用动态规划更好。对于下标i,其左边最高柱子要么是i-1左边最高柱子,要么是它自己本身,右侧同理。

class Solution
{
public:
    int trap(vector<int>& height)
    {
        int n = height.size();
        vector<int>left_max(n);
        vector<int>right_max(n);
        left_max[0] = height[0], right_max[n - 1] = height[n - 1];
        for (int i = 1; i < n; i++)
        {
            left_max[i] = max(left_max[i - 1], height[i]);
        }
        for (int i = n - 2; i >= 0; i--)
        {
            right_max[i] = max(right_max[i + 1], height[i]);
        }
        int ans = 0;
        for (int i = 0; i < n; i++)
        {
            ans += min(left_max[i], right_max[i]) - height[i];
        }
        return ans;
    }
};

和单调栈差不多。


网站公告

今日签到

点亮在社区的每一天
去签到