C++初阶:vector相关练习

本文介绍了多种编程问题,包括寻找只出现一次的数字、构建杨辉三角、删除有序数组重复项、查找出现次数超过一半的数以及电话号码字母组合的多叉树遍历。展示了位运算、排序、计数和递归等技术在解决这些问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 只出现一次的数

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    只出现一次的数
  3. 思路:位运算规律,a ^ a = 0,0 ^ a = a
class Solution 
{
public:
    int singleNumber(vector<int>& nums) 
    {
        int num = 0;
        for(auto e : nums)
        {
            num ^= e;
        }

        return num;
    }
};

2. 杨辉三角

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    杨辉三角
  3. 思路:将vector初始化为0,然后再将首尾处理为1,当num[i][j]为0时,nums[i][j] = nums[i - 1][j] + nums[i - 1][j - 1]
class Solution 
{
public:
    vector<vector<int>> generate(int numRows)
    {
        vector<vector<int>> vv;
        vector<int> v1(1, 1);
        vv.push_back(v1);
        if (numRows == 1)
        {
            return vv;
        }

        v1.push_back(1);
        vv.push_back(v1);
        if (numRows == 2)
        {
            return vv;
        }

        vector<int> v2(v1);
        for (int i = 1; i < numRows - 1; i++)
        {
            v2.push_back(1);
            for (int j = 1; j < v2.size() - 1; j++)
            {
                v2[j] = vv[i][j - 1] + vv[i][j];
            }
            vv.push_back(v2);
            v1 = v2;
        }

        return vv;
    }
};

优化:

class Solution 
{
public:
    vector<vector<int>> generate(int numRows) 
    {
        vector<vector<int>> ret;
        for(int i = 0; i < numRows; i++)
        {
            ret.push_back(vector<int>(i + 1));
            ret[i].front() = ret[i].back() = 1;
        }

        for(int i = 0; i < numRows; i++)
        {
            for(int j = 0; j < ret[i].size(); j++)
            {
                if(ret[i][j] == 0)
                {
                    ret[i][j] = ret[i - 1][j] + ret[i - 1][j - 1];
                }
            }
        }

        return ret;
    }
};

3. 删除有序数组中的重复项

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    删除有序数组中的重复项
  3. 思路:
    <1> 挪移覆盖法O(n^2)
    <2> 双指针法(快排),前提条件:有序

在这里插入图片描述

class Solution 
{
public:
    int removeDuplicates(vector<int>& nums) 
    {
        //双指针法
        int cur = 1;
        int pre = 0;
		
		//[0, pre]为不重复的数据,[pre + 1, cur]为未遍历过的数据
        //cur寻找未遍历过的数据,想不重复数据区间内插入
        while(cur < nums.size())
        {
            if(nums[pre] != nums[cur])
            {
                pre++;
                nums[pre] = nums[cur];
            }
            cur++;
        }

        return pre + 1;
    }
};

4. 只出现一次的数II

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    只出现一次的数II
  3. 思路:遍历计数法
class Solution 
{
public:
    int singleNumber(vector<int>& nums) 
    {
        sort(nums.begin(), nums.end());
        int count = 1;
        int i = 0;
        for(i = 0; i + 1 < nums.size(); i++)
        {
            if(nums[i] == nums[i + 1])
            {
                count++;
            }
            else
            {
                if(count != 3)
                {
                    break;
                }
                count = 1;
            }
        }

        return nums[i];
    }
};

5. 只出现一次的数III

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    只出现一次的数III
  3. 思路:排序 + 遍历计数
class Solution 
{
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        vector<int> v;
        sort(nums.begin(), nums.end());
        int count = 1;
        for(int i = 1; i < nums.size(); i++)
        {
            if(nums[i - 1] == nums[i])
            {
                count++;
            }
            else
            {
                if(count == 1)
                {
                    v.push_back(nums[i - 1]);
                }

                if(i == nums.size() - 1 && nums[i - 1] != nums[i])
                {
                    v.push_back(nums[i]);
                }

                count = 1;
            }
        }

        return v;
    }
};

6. 数组中出现次数超过一半的数

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    数组中出现次数超过一半的数
  3. 思路:排序 + 计数遍历
class Solution 
{
public:
    int MoreThanHalfNum_Solution(vector<int>& numbers) 
    {
        sort(numbers.begin(), numbers.end());
        int num = numbers[0];
        int count = 1;
        for(int i = 0; i + 1 < numbers.size(); i++)
        {
            if(count > numbers.size() / 2)
            {
                break;
            }

            if(numbers[i] != numbers[i + 1])
            {
                num = numbers[i + 1];
                count = 1;
            }
            else 
            {
                count++;
            }
        }

        return num;
    }
};

7. 电话号码的字母组合(多叉树遍历)

  1. 题目信息:
    在这里插入图片描述
  2. 题目链接:
    电话号码的字母组合
  3. 思路:多叉树遍历,递归:递归子函数的参数(递归需要的参数),递归的结束条件
class Solution
{
public:
	string data[10] = { "","","abc", "def","ghi","jkl","mno","pqrs","tuv","wxyz" };

    //先层数+1,再插入
    //count第几层
	void combine(vector<string>& ret, string& digits, int count, const string& ans)
	{
		//返回条件控制,什么时候返回
		if (count == digits.size())
		{
			ret.push_back(ans);
			return;
		}

		//多叉树遍历操作
		//pos第几个
		for (int pos = 0; pos < data[digits[count] - '0'].size(); pos++)
		{
			//字符串拼接,不更改原本的值,多次使用
			combine(ret, digits, count + 1, ans + data[digits[count] - '0'][pos]);
		}
	}

	vector<string> letterCombinations(string digits)
	{
		vector<string> ret;

		//特殊处理
		if (digits.size() == 0)
		{
			return ret;
		}

		//层数,当层的哪个字符
		//第几个答案,组成结果多次使用不可更改原值
		string ans;
		int count = 0;
		combine(ret, digits, count, ans);

		return ret;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值