只出现一次(N次)的数字 / 出现次数最多的数字 / 数组中数字出现的次数

news2024/11/17 10:05:29

一.题目类型简介

        数组中数字出现的次数是一类经典的问题,通常让我们求数组中数字出现的次数及其衍生的问题,比如,只出现一次的数字,只出现两次的数字,在一个数组中只有一个数字出现一次,其他出现两次或者三次,数组中出现次数最多,数组中出现的次数超过半数等。

二.经常使用的方法

        在这类题目中,我们可以使用暴力循环、HashMap、排序、异或运算等来解决,但是在面试等场景下,此类题目通常要求O(N)的时间复杂度和O(1)空间复杂度或者不使用额外空间,即比暴力解在时间和空间上要更优的方法。

三.典型例题

1.leetcode 136 只出现一次的数字

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

输入:nums = [2,2,1]
输出:1

输入:nums = [4,1,2,1,2]
输出:4

输入:nums = [1]
输出:1

排序

class Solution {
    public int singleNumber(int[] nums) {
        Arrays.sort(nums);
        for(int i = 0; i < nums.length-1; i += 2){
            if(nums[i] != nums[i+1]){
                return nums[i];
            }
        }
        return nums[nums.length-1];
    }
}

HashMap

class Solution {
    public int singleNumber(int[] nums) {
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            if(map.containsKey(nums[i])){
                map.put(nums[i],map.get(nums[i])+1);
            }
            else{
                map.put(nums[i],1);
            }
        }
        for(Map.Entry<Integer, Integer> entry : map.entrySet()){
            if(entry.getValue() == 1){
                return entry.getKey();
            }    
	    }
        return nums[0];
    }
}

HashSet优化 Ref.[1][2]

public static int singleNumber_HashSet(int[] nums) {

    int len = nums.length;
    Set<Integer> set = new HashSet<>();

    for (int i = 0; i < len; i++) {
        // 尝试将当前元素加入 set
        if (!set.add(nums[i])) {
            // 当前元已经存在于 set,即当前元素第二次出现,从 set 删除
            set.remove(nums[i]);
        }
    }

    // 最后只剩一个不重复的元素
    return set.iterator().next();
}

异或运算

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for(int i : nums){
            ans ^= i;
        }
        return ans;
    }
}

异或基本运算

和零运算:A\oplus 0 = A

本身运算:A\oplus A = 0

交换律和结合律:A\oplus B\oplus C = A\oplus C\oplus B = \left ( A\oplus B \right ) \oplus C

"必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。"按照题目的要求,只有此方法才满足,排序的时间是O(NlogN),而HashMap和HashSet的优化是O(N),但是空间上不满足要求,开辟了Hash空间,空间复杂度是O(N)的,只有异或的方法,或者说,本质上就希望我们使用异或的方法。

当在一个数组中只有一个数字出现了一次,我们不妨假设数组已经是排好序的,那么对于排好序的数组来说,有着一对一对的数,比如1和1,2和2,9和9,我们发现,1\oplus 1=0,其他一对相同的数字也是如此,最后只剩下了0和一个单个的数字,而A\oplus 0 = A

2.剑指 Offer II 004 只出现一次的数字 

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

输入:nums = [2,2,3,2]
输出:3

输入:nums = [0,1,0,1,0,1,100]
输出:100

排序

class Solution {
    public int singleNumber(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        for (int i = 0; i < n - 2; i += 3) {
            if (nums[i + 1] != nums[i]) return nums[i];
        }
        return nums[n - 1]; 
    }
}

HashMap

class Solution {
    public int singleNumber(int[] nums) {
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            if(map.containsKey(nums[i])){
                map.put(nums[i],map.get(nums[i])+1);
            }
            else{
                map.put(nums[i],1);
            }
        }
        for(Map.Entry<Integer, Integer> entry : map.entrySet()){
            if(entry.getValue() == 1){
                return entry.getKey();
            }    
	    }
        return nums[0];
    }
}

数位运算{Ref.3}

class Solution {
    public int singleNumber(int[] nums) {
        int ret = 0;
        for (int i = 0; i < 32; i++) {
            int cnt = 0;
            for (int num : nums) {
                cnt += num >> i & 1;
            }
            if (cnt % 3 != 0) {
                ret |= 1 << i;
            }
        }
        return ret;
    }
}

异或{Ref.4}

class Solution {
    public int singleNumber(int[] nums) {
        int one = 0, two = 0;
        for(int x : nums){
            one = one ^ x & ~two;
            two = two ^ x & ~one;
        }
        return one;
    }
}

本种方法思想牵扯到有限状态自动机,更多详情可参考[4]。

参考来源Ref.

[1] leetcode 神奇小超 通过哈希集、按位异或操作符解决(解题思路)

[2] leetcode ageovb 通过哈希集、按位异或操作符解决(解题思路)

[3] leetcode 清风Python 刷穿剑指offer-Day02-整数II 004.只出现一次的数字 位运算讲解 

[4] leetcode Krahets 剑指 Offer II 004. 只出现一次的数字(有限状态自动机 + 位运算,清晰图解)

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

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

相关文章

基于FPGA+JESD204B 时钟双通道 6.4GSPS 高速数据采集模块设计(二)研究 JESD204B 链路建立与同步的过程

基于 JESD204B 的采集与数据接收电路设计 本章将围绕基于 JESD204B 高速数据传输接口的双通道高速数据采集实现展 开。首先&#xff0c;简介 JESD204B 协议、接口结构。然后&#xff0c;研究 JESD204B 链路建立与同 步的过程。其次&#xff0c;研究基于 JESD204B …

linux驱动开发 - 10_阻塞和非阻塞 IO

文章目录 1 阻塞和非阻塞 IO1.1 阻塞和非阻塞简介1.2 等待队列1、等待队列头2、等待队列项3、将队列项添加/移除等待队列头4、等待唤醒5、等待事件 1.3 Linux驱动下的poll操作函数 2 阻塞 IO 实验1、驱动程序编写2、编写测试 APP3、编译驱动程序和测试 APP4、运行测试 3 阻塞 I…

elform 动态 rules

一.使用v-for渲染时 前端由于某些需求场景需要&#xff0c;部分表单的渲染是通过 v-for循环渲染显示&#xff0c;此时如何实现表单验证呢&#xff1f;如下&#xff0c;点击第一行的号可以动态的增加更多行表单&#xff0c;不同于单一固定的表单行[参见下文一般情况下]&#xf…

book-riscv-rev1.pdf 翻译(自用)第一章 操作系统接口

Job of operating system: 操作系统使得多个程序分享一台计算机&#xff0c;提供一系列仅靠硬件无法支持的服务。 管理与抽象低级别硬件&#xff08;如&#xff1a;文件处理程序不需要关注使用哪种硬盘&#xff09;使得多个程序分享硬件&#xff08;programs that can run at…

【代码练习】旋转矩阵题解思路记录分析

题目 给你一幅由 N N 矩阵表示的图像&#xff0c;其中每个像素的大小为 4 字节。请你设计一种算法&#xff0c;将图像旋转 90 度。 不占用额外内存空间能否做到&#xff1f; 示例 1: 给定 matrix [ [1,2,3], [4,5,6], [7,8,9] ], 原地旋转输入矩阵&#xff0c;使其变为: [ [7…

【C语言】学习

文章目录 前言1. warm up1.1 输出helloworld1.2 示例1.3 C语言程序结构 前言 以后要学习操作系统深度学习了&#xff0c;所以C语言就不可缺少了。 1. warm up 1.1 输出helloworld #include<stdio.h> void main() {printf("Hello World!!"); }std 标准 io输…

JS案例分析-某国际音x-tt-params参数分析

今天我们要分析的网站是&#xff1a;https://www.tiktok.com/selenagomez?langen&#xff0c;参数名字叫x-tt-params。 先来抓个包 这个接口是用户视频列表url&#xff0c;参数叫x-tt-params&#xff0c;该接口中还有其他参数像msToken&#xff0c;X-Bogus&#xff0c; _sig…

Cartesi 2023 年 4 月回顾

查看你不想错过的更新 2023年5月1日&#xff0c;感谢Cartesi生态系统中所有了不起的构建者&#xff01; 在一个激动人心的旅程之后&#xff0c;我们的首届全球线上黑客马拉松正式结束了&#xff01;有超过200名注册建造者参加&#xff0c;见证了所有参与者展示的巨大才华和奉献…

【Android】串口通信的理论与使用教程

Android系统诞生这十几年以来&#xff0c;Android开发工程师岗位经历了由盛转衰的过程&#xff0c;目前纯UI的Android APP已经鲜有公司愿意花费巨资去开发&#xff0c;Android APP开发的业务也仅剩游戏、物联网&#xff08;Internet of Things&#xff0c;简称IoT&#xff09;等…

springcloud:新一代分布式定时任务框架——PowerJob

0. 引言 之前我们讲解过主流的分布式定时任务框架xxl-job&#xff0c;随着技术的迭代更新&#xff0c;更多的定时任务框架也开始出现&#xff0c;今天我们来看一看新一代的定时任务框架PowerJob 1. PowerJob简介 PowerJob是基于java开发的企业级的分布式任务调度平台&#x…

Java设计原则之单一职责原则、开闭原则、里氏代换原则

文章目录 面向对象设计原则概述 单一职责原则 开闭原则 里氏代换原则 面向对象设计原则概述 软件的可维护性&#xff08;Maintainability&#xff09;和可复用性&#xff08;Reusability&#xff09;是两个非常重要的用于衡量软件质量的属性&#xff0c;软件的可维护性是指软…

Ubuntu常用命令总结

目录 1&#xff09;安装包命令及下载包命令 2&#xff09;阅读协议内容 3&#xff09;执行sh文件&#xff1a; 4&#xff09;创建虚拟环境 5&#xff09;激活虚拟环境 6&#xff09;虚拟环境中安装包 7&#xff09;安装上传代码工具 8&#xff09;代码上传 9&#xff09…

传输控制协议(TCP)知识点总结

文章目录 传输控制协议&#xff08;TCP)知识点总结介绍数据包格式TCP连接的建立和关闭三次握手四次挥手一张图展示这些过程 其他知识 传输控制协议&#xff08;TCP)知识点总结 维基百科: 传输控制协议&#xff08;TCP&#xff09;是Internet协议套件中的主要协议之一。它起源于…

五种最危险的新兴网络攻击技术

SANS研究所的网络专家揭示了包括网络罪犯和民族国家行为者在内的网络攻击者正在使用的五种最危险的新兴网络攻击技术。在旧金山举行的RSA网络安全会议上&#xff0c;由SANS研究所的几位分析师组成的讨论组讨论了新兴的网络攻击战术、技术和程序&#xff0c;并提供了如何为企业做…

使用GLSL来实现实时滤镜的效果

1. 先来明确几个概念 1.1 OpenGL OpenGL 全称为 Open Graphics Library&#xff08;开放图形库&#xff09;。 是用于渲染 2D 或 3D 图像的跨语言跨平台的应用程序编程接口&#xff0c;用于CPU控制GPU做图像渲染&#xff0c;是一套API。 提供设计人员一个共同的硬件驱动标准…

虚函数、静态绑定和动态绑定

静态绑定 class Base { public:Base(int data) :ma(data) {}void show() { cout << "Base::show()" << endl; }void show(int) { cout << "Base::show(int)" << endl; }protected:int ma; };class Derive : public Base { public…

Go | 一分钟掌握Go | 10 - 反射

作者&#xff1a;Mars酱 声明&#xff1a;本文章由Mars酱编写&#xff0c;部分内容来源于网络&#xff0c;如有疑问请联系本人。 转载&#xff1a;欢迎转载&#xff0c;转载前先请联系我&#xff01; 前言 反射你以为只在Java中有吗&#xff1f;Go也有反射机制&#xff0c;很多…

【JavaEE】应用层自定义协议及UDP协议

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 本篇文章将为大家介绍应用层中UDP协议~~ 在应用层这里&#xff0c;虽然存在一些现有的协议&#xff08;HTTP&#xff09;&#xff0c;但是也有很多情况&#xff0c;需要程序猿自定制协议&a…

OJ 功能介绍 使用手册

目录 服务器配置 OJ界面展示 用户管理 一、批量导入&#xff08;从方便管理角度建议以 学生姓名 作为 用户名 &#xff09; 二、批量生成临时用户 后期修改成需要的用户名和密码 &#xff08;学生登录后修改密码&#xff09; 三、用户自行注册&#xff08;填写邮箱获取验证码…

Nmap入门到高级【第九章】

预计更新Nmap基础知识 1.1 Nmap简介和历史 1.2 Nmap安装和使用方法 1.3 Nmap扫描技术和扫描选项 Nmap扫描技术 2.1 端口扫描技术 2.2 操作系统检测技术 2.3 服务和应用程序检测技术 2.4 漏洞检测技术 Nmap扫描选项 3.1 扫描类型选项 3.2 过滤器选项 3.3 探测选项 3.4 输出选项…