leetcode 75.颜色分类


LeetCode第75题“颜色分类”要求对包含红色、白色和蓝色的数组进行排序,红色、白色和蓝色分别用0、1和2表示。这个问题可以通过荷兰国旗问题的解决方案来实现,该算法的时间复杂度为O(N),空间复杂度为O(1)。

方法一

代码实现

我们可以使用双指针(two-pointer)的方法来解决这个问题:

#include <vector>
#include <iostream>

using namespace std;

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int left = 0, right = nums.size() - 1, current = 0;
        
        while (current <= right) {
            if (nums[current] == 0) {
                swap(nums[current], nums[left]);
                left++;
                current++;
            } else if (nums[current] == 1) {
                current++;
            } else if (nums[current] == 2) {
                swap(nums[current], nums[right]);
                right--;
            }
        }
    }
};

int main() {
    Solution solution;
    vector<int> nums = {2, 0, 2, 1, 1, 0};
    solution.sortColors(nums);
    
    for (int num : nums) {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}

解释

  1. 初始化三个指针

    • left 指向最左边的0的下一个位置。
    • right 指向最右边的2的前一个位置。
    • current 用于遍历数组。
  2. 遍历数组并进行交换

    • 如果 nums[current] 为0,则与 nums[left] 交换,同时将 leftcurrent 指针都向右移动一位。
    • 如果 nums[current] 为1,则仅将 current 向右移动一位。
    • 如果 nums[current] 为2,则与 nums[right] 交换,同时将 right 指针向左移动一位,但 current 不移动,因为交换过来的值还需要处理。

关键点

  • 通过交换 nums[current]nums[left],我们确保所有0都在数组的左边。
  • 通过交换 nums[current]nums[right],我们确保所有2都在数组的右边。
  • 所有1都将自动排在中间。

时间复杂度和空间复杂度

  • 时间复杂度:O(N),因为我们只需要遍历数组一次。
  • 空间复杂度:O(1),因为我们只使用了常数级别的额外空间。

这种方法高效且简单,适用于大多数情况下需要对包含少数类别的数组进行分类排序的场景。

方法二

有一个简单的思路,这种方法虽然简单直观,但它不是题目要求的单次遍历解决方案。不过,对于理解问题和学习排序的基本概念非常有帮助。可以分为两个步骤:

  1. 第一次遍历:统计数组中0、1、2的出现次数。
  2. 第二次遍历:根据统计结果重新填充数组。

代码实现

#include <vector>
#include <iostream>

using namespace std;

class Solution {
public:
    void sortColors(vector<int>& nums) {
        // Step 1: Count the number of 0s, 1s, and 2s
        int count0 = 0, count1 = 0, count2 = 0;
        for (int num : nums) {
            if (num == 0) {
                count0++;
            } else if (num == 1) {
                count1++;
            } else if (num == 2) {
                count2++;
            }
        }
        
        // Step 2: Overwrite the array with the sorted order
        int index = 0;
        for (int i = 0; i < count0; i++) {
            nums[index++] = 0;
        }
        for (int i = 0; i < count1; i++) {
            nums[index++] = 1;
        }
        for (int i = 0; i < count2; i++) {
            nums[index++] = 2;
        }
    }
};

int main() {
    Solution solution;
    vector<int> nums = {2, 0, 2, 1, 1, 0};
    solution.sortColors(nums);
    
    for (int num : nums) {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}

解释

  1. 统计0、1、2的出现次数

    int count0 = 0, count1 = 0, count2 = 0;
    for (int num : nums) {
        if (num == 0) {
            count0++;
        } else if (num == 1) {
            count1++;
        } else if (num == 2) {
            count2++;
        }
    }
    
    • 遍历数组,使用三个变量 count0count1count2 分别统计0、1、2的出现次数。
  2. 重新填充数组

    int index = 0;
    for (int i = 0; i < count0; i++) {
        nums[index++] = 0;
    }
    for (int i = 0; i < count1; i++) {
        nums[index++] = 1;
    }
    for (int i = 0; i < count2; i++) {
        nums[index++] = 2;
    }
    
    • 使用 index 变量从头开始填充数组。
    • 先填充 count0 个0,再填充 count1 个1,最后填充 count2 个2。

时间复杂度和空间复杂度

  • 时间复杂度:O(N),因为我们遍历了数组两次。
  • 空间复杂度:O(1),因为我们只使用了常数级别的额外空间。

方法三(单指针)

#include <vector>
using std::vector;
/*
 * @lc app=leetcode.cn id=75 lang=cpp
 *
 * [75] 颜色分类
 */

// @lc code=start
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int index = 0;
        for(int i = 0;i < nums.size() ;i++){
            if(nums[i] == 0){
                swap(nums,i,index);
                index ++;
            }
        }
        for(int i = 0; i < nums.size();i++){
            if(nums[i] == 1){
                swap(nums,i,index);
                index ++;
            }
        }
    }
    void swap(vector<int>& nums,int index1,int index2){
        int  temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
};
// @lc code=end


方法四(双指针)

#include <vector>
using std::vector;
/*
 * @lc app=leetcode.cn id=75 lang=cpp
 *
 * [75] 颜色分类
 */

// @lc code=start
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int left = 0;
        int right = nums.size() - 1;
        for(int i = 0;i <= right;i++){
            if(nums[i] == 0){
                swap(nums,i,left);
                left ++;
            }else if(nums[i] == 2){
                swap(nums,i,right);
                right --;
                if(nums[i] != 1){
                    i --;
                }
            }
        }
    }
    void swap(vector<int>& nums,int index1,int index2){
        int  temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
};
// @lc code=end


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值