《vector的一些OJ》

news2024/11/25 6:35:57

本文主利用我们的vector来解决一些OJ题
前三个题目很类似,分别为

  1. 一个数字只出现一次,其他数字都出现两次
  2. 两个数字只出现一次,其他数字都出现两次
  3. 一个数字只出现一次,其他数字都出现三次

文章目录

  • 1、[一个只出现一次的数字,其他数字都出现两次](https://leetcode-cn.com/problems/single-number/submissions/)
  • 2、[两个只出现一次的数字,其他数字都出现两次](https://leetcode.cn/problems/single-number-iii/)
  • 3、[一个只出现一次的数字,其他数字都出现三次](https://leetcode-cn.com/problems/single-number-ii/)
  • 4、[删除数组中的重复项](https://leetcode.cn/problems/remove-duplicates-from-sorted-array/)
  • 5、[杨辉三角](https://leetcode.cn/problems/pascals-triangle/)
  • 6、[电话号码字母组合](https://leetcode.cn/problems/letter-combinations-of-a-phone-number/submissions/)
  • 7、[数组中出现次数超过一半的数字](https://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163?tpId=13&&tqId=11181&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking)


1、一个只出现一次的数字,其他数字都出现两次

在这里插入图片描述
思路:这个其实很简单,我们使用异或的思想即可。因为两个相同的数异或的结果为0,任何数和0异或都等于他本身。

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int ret = 0;
        for(auto e:nums) //遍历数组,将所有数字异或
        {
            ret^=e;
        }
        return ret;
    }
};

2、两个只出现一次的数字,其他数字都出现两次

在这里插入图片描述
思路1:我们使用排序思想。

  1. 首先将数组的数组进行排序sort()
  2. 定义一个数组ret存储要返回的这个两个数。
  3. 然后遍历数组,如果当前的数字和后一个相等,那么就跳两步,如果不行等就将这个数字放在ret里面。向后跳一步继续寻找。
    注意:这个循环的截至条件为数组元素的最后一个,为了防止越界。
  4. 出了循环判断i是否在最后一个位置,如果是,那最后一个元素也是只出现一次的。因为我们使用的是当前数字和后面一个比较的,如果不相等只会向后跳一步。
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());
        vector<int> ret;
        int i = 0;
        //防止越界
        for(;i < nums.size() - 1;)
        {
            if(nums[i] == nums[i+1])
            {
                i+=2;
            }
            else
            {
                ret.push_back(nums[i]);
                i+=1;
            }
        }
        
        //将最后一个元素插入
        if(i == nums.size() - 1)
        {
            ret.push_back(nums[i]);
        }
        return ret;
    }
};

思路2:使用异或思想

  1. 遍历nums,通过异或操作,得到结果 s = a ^ b(a, b为恰好只出现一次的元素)
  2. 保留s的最后为1的那位保留,其余位置设置为0 ,存入在 k 里面 (如:k = 0000 0100)
  3. knums中的每一个元素进行 & 操作,可以把nums中所有元素,划分为两组(如:一组0000 0000 , 二组:0000 0100,这样a , b 被划分到不同组中,在对每一个组进行异或,即可提取出a 和 b 了)

注意:这个赋值给k时候需要加一个判断条件。因为与运算的结果可能负数的最大值,最高位是符号位

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        int s = 0;
        for(int e : nums)
        {
            s ^= e;
        }

        int k = (s == INT_MIN ? s :s & (-s)); //因为s是两个单身狗^后的结果,一定有一个为1另外一个为0,使用s&(-s)可以使得这个位为1,其他位为0


        //将k与原数组进行&操作,将其分为两组,这样,两个单身狗就被分到两个组了
        vector<int> RetNums(2,0);
        for(int e : nums)
        {
            if(k & e)
            {
                RetNums[0] ^= e;
            }
            else
            {
                RetNums[1] ^= e;
            }
        }
        return RetNums;
    }
};

3、一个只出现一次的数字,其他数字都出现三次

在这里插入图片描述

思路:这个也是用排序的思想,和上面类似,无非是条两步还是跳三步的区别

  1. 首先将数组进行排序sort()
  2. 遍历数组,将当前位置和后面一个位置进行比较,如果相等则向后跳三步,否则返回这个位置的值。

注意:这个需要再加一个判断条件,当i在最后一个位置时候也直接返回。因为每次都跳三步,都是跳到下一个不同值元素的位置。当在结尾时候,说明最后一个就是单身狗

//1:先排序
//2:然后遍历数组,如果是最后一个元素,或者当前位置的元素和后面一个不相等,那么就返回当前位置的值,否则,i+=3
//3:如果为空,则返回最后一个

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());
       
        for(int i = 0;i < nums.size();i+=3)
        {
            if(i == nums.size() - 1 || nums[i] != nums[i+1])
            {
                return nums[i];
            }
        }
        //return nums[nums.size() - 1];
        return 0;
    }
};

4、删除数组中的重复项

在这里插入图片描述
思路:因为是原地修改,我们使用双指针,一个用来遍历数字,一个用来修改数组

  1. 定义两个数,src=dest=0
  2. 遍历数组,如果src和dest位置的值相等就将src++,不相等我们才修改数组。(先将dest++,再将src位置的值赋值给dest位置的值。然后src++)
  3. 最后数组的长度就是dest+1
class Solution {
public:
    int removeDuplicates(vector<int>& nums) 
    {
        size_t src = 0;
        size_t dest = 0;
        for(size_t i = 0;i < nums.size();++i)
        {
            if(nums[src] == nums[dest])
            {
                ++src;
            }
            else
            {
                ++dest;
                nums[dest] = nums[src];
                ++src;
            }
        }
        return dest+1;
    }
};

5、杨辉三角

在这里插入图片描述
思路:使用vector<vector< int >>
最外层的vector其实相当于存的是一堆数组指针,指向的是每个一维数组。里面的vector是一维数组,里面存的是数字。

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> generate(int numRows) 
    {
        //开空间初始化
        vector<vector<int>> vv;
        vv.resize(numRows,vector<int>()); //里面初始化为匿名的对象
        for(size_t i = 0;i < vv.size();++i)
        {
            vv[i].resize(i+1,0);
            vv[i][0] = 1;
            vv[i][vv[i].size() - 1] = 1;
        }

        for(size_t i = 0;i < vv.size();++i)
        {       
           //遍历每一个vector<int>赋值
            for(size_t j = 0; j < vv[i].size();++j)
            {
                if(vv[i][j] == 0)
                {
                    vv[i][j] = vv[i-1][j] + vv[i-1][j-1];
                }
            }
        }
        return vv;
    }
};

6、电话号码字母组合

在这里插入图片描述
思路:其实就是使用多叉树深度遍历的思想。代码不难,逻辑有点麻烦

图解:
在这里插入图片描述

//1:首先定义一个数组,数组里面每个元素数string类(每个数字对应的字符串)
//2:定义一个vector<string> vv,这个对象是一个数组,里面每个元素是一个string,最后我们将所有的组合串尾插到这个数组中

//定义一个组合函数,参数分别为  //输入的数字串,第几个数字,组合的字母串,返回的那个string类型的数组



class Solution {
public:
    //数字串
    string _numberStr[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

    //输入的数字串,第几个数字,组合的字母串,string类型的数组
    void Combination(const string& digits,size_t di,string CombineStr,vector<string>& Strv)
    {
        if(di == digits.size())
        {
            Strv.push_back(CombineStr); //将组合串尾插数组
            return;
        }
        //1:首先取数字
        size_t num = digits[di] - '0';
        //2:找到数字对应的字串
        string str = _numberStr[num];
        //3:遍历字串,然后组合并且递归下去
        for(auto ch : str)
        {
            Combination(digits,di + 1,CombineStr + ch,Strv); //递归下一层
        }
    }

    vector<string> letterCombinations(string digits) 
    {

        vector<string> Strv; //string 类型的数组
        if(digits.size() == 0)
        {
            return Strv;
        }
        Combination(digits,0,"",Strv);
        return Strv;
    }
};

7、数组中出现次数超过一半的数字

在这里插入图片描述

方法1:
思路:这个很简单,我们先把数组排序,然后遍历数组,当前位置和后;一个不相等就++i,相等就静茹循环计数,然后判断。

//思路:
//1:先排序
//2:然后遍历数组,这个注意要防止越界,如果前一个元素和后一个不相等,那么++i
//如果前一个和后一个相等,那么进入循环,我们来记计数。这个也要注意防止越界,结束后判断一下是不是大于长度的一般,大于就返回当前位置的值,否则将count置为1

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) 
    {
    	if(numbers.size() == 0)
    		return 0;
        //先排序
        std::sort(numbers.begin(),numbers.end());

        size_t len = numbers.size();//数组长度
        size_t i = 0;
        size_t count = 1;//相同元素个数
        while(i < len - 1) 
        {
            if(numbers[i] != numbers[i+1])
            {
                ++i;
            }
            else
            {
                while(i < len - 1 && numbers[i] == numbers[i+1])
                {
                    ++count;
                    ++i;
                }
                if(count > len/2)
                    return numbers[i];
            }
            count = 1;
        }
        return numbers[i];
    }
};

方法2:
1:先排序,题目说一定有解,那么一定是中间那个数字(因为这个数组超过了数组长度的一半)。
2:然后遍历数组,统计他的次数,最后判断一下他的次数是不是大于一般,大于则返回这个数,否则返回0。

注:其实第二部都是多余的,有解,那么就是中间这个数,直接返回就行了

//思路:
//1:先排序
//2:如果有解,那么一定是中间的数字

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) 
    {
        //先排序
        std::sort(numbers.begin(),numbers.end());

        //超过一般的那个数字
        int middle = numbers[numbers.size()/2];
        //这里其实直接返回就行了,因为一定会有解,那就是中间这个数字了!!
        //return numbers[numbers.size()/2]
        int count = 0;
        size_t i = 0;
        while(i < numbers.size())
        {
            if(numbers[i] = middle)
                ++count;
            ++i;
        }
        return (count > numbers.size()/2) ? middle : numbers[0];    
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/499475.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3:自定义指令

一、理解vue指令 1.1、指令 在 vue 中提供了一些对于页面和数据更为方便的输出&#xff0c;这些操作就叫做指令&#xff0c;以 v-xxx 表示&#xff0c;比如 html 页面中的属性 <div v-xxx ></div>。自定义指令很大程度提高了开发效率&#xff0c;提高了工程化水平…

Makefile基础教程(伪目标)

文章目录 前言一、伪目标概念二、进一步了解伪目标三、不使用.PHONY来定义伪目标总结 前言 本篇文章将讲解Makefile中的伪目标&#xff0c;Makefile的目标在前面的文章中我们已经讲解了那么这篇文章我们就来讲讲伪目标。 一、伪目标概念 Makefile 伪目标是一类特殊的目标&am…

手机摄影(四)

第8章 人物拍摄 平拍显亲切 如果侧拍好看&#xff0c;可以选择 局部自拍表现神秘&#xff08;比如嘴唇&#xff0c;眼睛&#xff0c;锁骨&#xff0c;要足够惊艳&#xff09; 技巧&#xff1a; 简单背景适合人像和镜子回头&#xff08;幅度不能太大&#xff09;小清新&…

《NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis》论文精读

Abstract 我们提出了一种方法&#xff0c;通过使用稀疏的输入视图集优化底层连续体场景函数&#xff0c;实现了合成复杂场景新视图的最先进结果。我们的算法使用全连接(非卷积)深度网络表示场景&#xff0c;其输入是单个连续的5D坐标(空间位置(x, y, z)和观看方向(θ&#xff…

C++系列五:输入/输出

C输入输出 1. 输入2. 输出3. 格式化输出4. 总结 1. 输入 输入是指从外部源获得数据的过程&#xff0c; C中可通过键盘或文件等外部源来获取输入数据。 &#xff08;1&#xff09;cin cin是C标准库中的一个输入流对象&#xff0c;用于从标准输入设备&#xff08;通常是键盘&a…

如何评价滤波器的去噪效果?

假如使用两种滤波器&#xff0c;那么滤波效果如何去评价1&#xff1f; 为了能够得到高质量的去噪后信号&#xff0c;需要对滤波器的滤波效果进行评价&#xff0c;选取去噪效果最好的滤波器对原始信号进行去噪处理。 一般使用信噪比和峰值信噪比对滤波器进行量化评价&#xff0c…

Docker 基础实战:环境搭建、容器、仓库、镜像

文章目录 Docker 基础实战环境搭建容器启动容器新建并启动容器终止容器启动已终止容器创建守护态容器 容器日志查看日志日志驱动 进入容器docker attachdocker exec 容器信息docker psdocker inspectdocker topdocker stats 删除容器容器快照导出快照导入快照 仓库Docker Hub本…

软考--快速掌握七层模型与各种协议的划分

目录 协议族 网络层涉及的协议 传输层涉及的协议 应用层涉及的协议 协议族 认识几个协议族&#xff0c;所谓协议族就是说他不是单一的协议。而是很多协议拼在一起的。 TCP/IP协议族是internet的标准协议族&#xff0c;所以使用广&#xff0c;但是tcp/ip协议族传输效率是比较…

面试题:String,StringBuilder和StringBuffer的区别

面试题&#xff1a;String&#xff0c;StringBuilder和StringBuffer的区别 一、String 1、String是一个长度不可变的字符序列&#xff0c;底层是一个被final修饰的char[]数组。 2、任何对String类型进行改变的操作实际上都是重新生产一个新的String对象&#xff0c;然后将指…

micro-app在vue-element-admin中一些使用研究

1、简述 本文承接上一篇micro-app在vue-element-admi中的搭建&#xff0c;对micro-app在vue-element-admin中的一些平时开发中常用的功能做了一些研究。本文代码 2、路由 关于路由&#xff0c;这边从两方面进行研究&#xff0c;一方面是对菜单的配置&#xff0c;另一方面是页…

❤ 个人博客的搭建和设置

❤ 个人博客的搭建和设置 闲暇时候自己试着做了一个自己的个人博客&#xff0c;博客使用的Github进行托管&#xff0c;还在阿里云买了属于自己的域名 具体步骤如下 1、登陆自己的博客账号&#xff0c;新建个人主页的仓库 2、到了我们的名字设置&#xff0c;格外注意&#xf…

Leetcode刷题之两两交换链表中的结点和相交链表

只有把抱怨环境的心情&#xff0c;化为上进的力量&#xff0c;才是成功的保证。 ——罗曼罗兰目录 &#x1f349;一.相交链表 &#x1f490;1.双指针 &#x1f34d;2.计算长度加双指针 &#x1f352;二.两两交换链表中的结点 &#x1f34c;1.迭代 &#x1f349;一…

【Golang】多线程下载器的实现

〇、前言 多线程下载&#xff0c;顾名思义就是对一个文件进行切片访问&#xff0c;等待所有的文件下载完成后在本地进行拼接成一个整体文件的过程。 因此可以利用 golang 的多协程对每个分片同步下载&#xff0c;之后再合并且进行md5校验或者总长度校验。 一、请求资源 下载…

5.7学习周报

文章目录 前言文献阅读摘要简介数据方法论预测结果结论 时间序列预测总结 前言 本周阅读文献《Water quality forecasting based on data decomposition, fuzzy clustering and deep learning neural network》&#xff0c;文献主要结合数据分解、模糊C均值聚类和双向门控循环…

设计模式 - 工厂方法模式

设计模式 - 工厂方法模式 1、关于工厂方法模式2、工厂方法模式小试牛刀2.1、类图2.2、代码清单3、工厂方法模式的扩展3.1、简单工厂模式&#xff08;静态工厂模式&#xff09; 1、关于工厂方法模式 工厂方法模式&#xff0c;就是定义一个用于创建对象的接口&#xff0c;让子类决…

Ubuntu20升级nodejs版本

执行 grunt build的时候提示node版本过低 当前版本为10.19.0&#xff0c;不满足要求 安装 n&#xff0c;用于更新 node 版本的 sudo npm install n -g用n 下载 nodejs 的最新稳定版本 sudo n stable3. 安装完毕&#xff0c;node -r检查当前版本

【算法与数据结构】链表

链表 链表&#xff1a;结构定义 链表是由一串节点串联在一起的&#xff0c;链表的每个节点存储两个信息&#xff1a;数据下一个节点的地址 分清楚两个概念&#xff1a;什么是内存内部&#xff0c;什么是程序内部 内存内部&#xff1a; 信息存储在内存空间里的 程序内部&#…

复习笔记1

考纲(张友生版本软件架构 考试题型&#xff1a; 10*3单选 5*3简答题 5*3设计图&#xff08;含画图&#xff09; 10*2 论述题 10*2综合题 复习以课件为主&#xff0c;书为辅 第一章 (软件危机) &#xff1f; &#xff1f; 构造模型与实现 掌握软件结构体系核心模型 第二章 软件体…

阿里云Alibaba Cloud Linux镜像系统介绍及常见问题解答FAQ

阿里云服务器操作系统Alibaba Cloud Linux镜像怎么样&#xff1f;可以代替CentOS吗&#xff1f;Alibaba Cloud Linux兼容性如何&#xff1f;有人维护吗&#xff1f;漏洞可以修复吗&#xff1f;Alibaba Cloud Linux完全兼容CentOS&#xff0c;并由阿里云官方免费提供长期维护。 …

Java并发,夺命 60 问

基础 1.并行跟并发有什么区别&#xff1f; 从操作系统的角度来看&#xff0c;线程是CPU分配的最小单位。 并行就是同一时刻&#xff0c;两个线程都在执行。这就要求有两个CPU去分别执行两个线程。 并发就是同一时刻&#xff0c;只有一个执行&#xff0c;但是一个时间段内&am…