牛客经典101题题解集--哈希

目录

哈希

两数之和

题目

分析

代码

java

python

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

题目

代码

java

python

数组中只出现一次的两个数字

题目

分析

代码

java

python

缺失的第一个正整数

题目

分析

代码

java

python

三数之和

题目

分析

代码

java

python


哈希

两数之和

题目

给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。

(注:返回的数组下标从1开始算起,保证target一定可以由数组里面2个数字相加得到)

数据范围:2≤𝑙𝑒𝑛(𝑛𝑢𝑚𝑏𝑒𝑟𝑠)≤105,−10≤𝑛𝑢𝑚𝑏𝑒𝑟𝑠𝑖≤109,0≤𝑡𝑎𝑟𝑔𝑒𝑡≤109

要求:空间复杂度 𝑂(𝑛),时间复杂度 𝑂(𝑛𝑙𝑜𝑔𝑛)

示例1

输入:3,2,4,6

返回值:2,3

说明:因为 2+4=6 ,而 2的下标为2 , 4的下标为3 ,又因为 下标2 < 下标3 ,所以返回2,3

示例2

输入:20,70,110,150,90

返回值:1,2

说明:20+70=90

分析

记住哈希表可以快速查找某个元素是否存在。

代码

java
java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型一维数组 
     * @param target int整型 
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        // write code here
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<numbers.length;i++){
            int x=numbers[i];
            if(map.containsKey(target-x)){
                return new int[]{map.get(target-x)+1,i+1};
            }
            map.put(x,i);
        }
            
        return new int[0];  
        
        }
    }
python
python 复制代码
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param numbers int整型一维数组 
# @param target int整型 
# @return int整型一维数组
#
class Solution:
    def twoSum(self , numbers: List[int], target: int) -> List[int]:
        # write code here
        index={}
        for j,x in enumerate(numbers):
            if target-x in index:
                return [index[target-x]+1,j+1]
            index[x]=j

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

题目

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如输入一个长度为9的数组1,2,3,2,2,2,5,4,2。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

数据范围:𝑛≤50000,数组中元素的值 0≤𝑣𝑎𝑙≤10000

要求:空间复杂度:𝑂(1),时间复杂度 𝑂(𝑛)

输入描述:

保证数组输入非空,且保证有解

示例1

输入:1,2,3,2,2,2,5,4,2

返回值:2

示例2

输入:3,3,3,3,2,2,2

返回值:3

示例3

输入:1

返回值:1

代码

java
java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型一维数组 
     * @return int整型
     */
    public int MoreThanHalfNum_Solution (int[] numbers) {
        // write code here
        Map<Integer,Integer> map=new HashMap<>();
        for(int i:numbers){
            if(map.containsKey(i)){
                map.replace(i,map.get(i)+1);
            }else{
                map.put(i,1);
            }
        }
        for(int i:map.keySet()){
            if(map.get(i)>numbers.length/2){
                return i;
            }
        }
        return -1;
    }
}
python
python 复制代码
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param numbers int整型一维数组 
# @return int整型
#
class Solution:
    def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int:
        # write code here
        index={}
        for num in numbers:
            if num in index:
                index[num]+=1
            else:
                index[num]=1
        for key in index:
            if index[key]>len(numbers)/2:
                return key
        return -1

                

数组中只出现一次的两个数字

题目

一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

数据范围:数组长度 2≤𝑛≤1000,数组中每个数的大小 0<𝑣𝑎𝑙≤1000000

要求:空间复杂度 𝑂(1),时间复杂度 𝑂(𝑛)

提示:输出时按非降序排列。

示例1

输入:1,4,1,6

返回值:4,6

说明:返回的结果中较小的数排在前面

示例2

输入:1,2,3,3,2,9

返回值:1,9

分析

首先要知道 a^b^a=a^a^b=b,如果数组中除了某一个数字,其他数字都出现了两次,找出该数字。思路就是遍历数组,对每一个数字都求异或,最后得到的值就是要找的数字。

本题是要找两个数字a和b,那我们把该数组分成两个数组,其中a和一部分出现两次的数字在一块儿,b和另一部分出现两次的数字在一块儿,然后再分别对这两个数组求异或,就可以找到这两个数字了。

怎么把a和b区分开来?

可以利用二进制来区分。先对整个数组求异或得到c,根据上面的知识,可以知道c其实就是a^b=c。那么对于c,假如c二进制的第一位是1,其实就代表a二进制的第一位是1(或0),b二进制的第一位是0(或1),总而言之如果第一位的c等于1,那么a和b在第一位肯定不相等。

所以我们就可以想到利用二进制的第一位(有可能是第二位,第三位 。。。因为上面是假设的c第一位是1)为1来区分两个数组,第一位为1的是数组一,第一位为0的是数组二。这样就相当于把a和b给区分开来了。

代码

java
java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型一维数组 
     * @return int整型一维数组
     */
    public int[] FindNumsAppearOnce (int[] nums) {
        // write code here
        if(nums==null || nums.length==0){
            return new int[0];
        }
        int res=0;
        for(int x:nums){
            res=res^x;
        }
         // 第二步:找到第一个为 1 的二进制位 index
        int index = 0;
        while ((res & 1) == 0) {
            res = res >> 1;
            index++;
        }
        // 第三步:分组异或
        int a = 0, b = 0;
        for (int num : nums) {
            if (helper(num, index)) {
                a ^= num;
            } else {
                b ^= num;
            }
        }
        return a < b ? new int[]{a, b} : new int[]{b, a};
    }
    // 辅助函数:判断数字 num 第 index 位是否为 1
    private boolean helper(int num, int index) {
        num = num >> index;
        return (num & 1) != 0;
    }
}
python
python 复制代码
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param nums int整型一维数组 
# @return int整型一维数组
#
class Solution:
    def FindNumsAppearOnce(self , nums: List[int]) -> List[int]:
        # write code here
        if not nums:
            return []
    
    # 第一步:整个数组异或,得到 a ^ b
        res = 0
        for x in nums:
            res ^= x
    
    # 第二步:找到第一个为 1 的二进制位 index
        index = 0
        while (res & 1) == 0:
            res = res >> 1
            index += 1
    
    # 第三步:根据第 index 位分组异或
        a, b = 0, 0
        for num in nums:
            if self.helper(num, index):
                a ^= num
            else:
                b ^= num
    
    # 按升序返回
        return [a, b] if a < b else [b, a]

# 辅助函数:判断数字 num 第 index 位是否为 1
    def helper(self,num, index):
        num = num >> index
        return (num & 1) != 0

缺失的第一个正整数

题目

给定一个无重复元素的整数数组nums,请你找出其中没有出现的最小的正整数

进阶: 空间复杂度 𝑂(1),时间复杂度 𝑂(𝑛)

数据范围:

−231≤𝑛𝑢𝑚𝑠𝑖≤231−1

0≤𝑙𝑒𝑛(𝑛𝑢𝑚𝑠)≤5∗105

示例1

输入:1,0,2

返回值:3

示例2

输入:-2,3,4,1,5

返回值:2

示例3

输入:4,5,6,8,9

返回值:1

分析

想象有一间教室,座位从左到右编号为 1 到 n。

有 n 个学生坐在教室的座位上,把 numsi 当作坐在第 i 个座位上的学生的学号。我们要做的事情,就是让学号在 1 到 n 中的学生,都坐到编号与自己学号相同的座位上(学号与座位编号匹配)。学号不在 1,n 中的学生可以忽略。

学生们交换座位后,从左往右看,第一个学号与座位编号不匹配的学生,其座位编号就是答案。

特别地,如果所有学生都坐在正确的座位上,那么答案是 n+1。
假设数组的下标是从 1 开始的。

假设 nums=2,3,1

从 nums1 开始。这个座位上的学生,学号是 2,他应当坐在 nums2 上,所以他和 nums2 交换。交换后 nums=3,2,1

仍然看 nums1,这个座位上的学生,学号是 3,他应当坐在 nums3 上,所以他和 nums3 交换。交换后 nums=1,2,3

仍然看 nums1,这个座位上的学生,学号是 1,他坐在正确的座位上。

向后遍历,nums2=2,他坐在正确的座位上。

向后遍历,nums3=3,他坐在正确的座位上。

换座位过程结束。

再次遍历 nums,发现 numsi=i 都满足,说明数组中 1,2,3 都有,所以缺失的第一个正数是 4。

代码

java
java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型一维数组 
     * @return int整型
     */
    public int minNumberDisappeared (int[] nums) {
        // write code here
        int n=nums.length;
        for(int i=0;i<nums.length;i++){
            while(1<=nums[i] && nums[i]<=n && nums[nums[i]-1]!=nums[i]){
                int j=nums[i]-1; // 减一是因为数组下标从 0 开始
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
        }
        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }
        return n+1;
    }
}
python
python 复制代码
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param nums int整型一维数组 
# @return int整型
#
class Solution:
    def minNumberDisappeared(self , nums: List[int]) -> int:
        # write code here
        n=len(nums)
        for i in range(n):
            while nums[i]>=1 and nums[i]<=n and nums[nums[i]-1]!=nums[i]:
                j=nums[i]-1
                temp=nums[i]
                nums[i]=nums[j]
                nums[j]=temp
        for i in range(n):
            if nums[i]!=i+1:
                return i+1
        return n+1

三数之和

题目

给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。

数据范围:0≤𝑛≤1000,数组中各个元素值满足 ∣𝑣𝑎𝑙∣≤100

空间复杂度:𝑂(𝑛2),时间复杂度 𝑂(𝑛2)

注意:

  1. 三元组(a、b、c)中的元素必须按非降序排列。(即a≤b≤c)
  2. 解集中不能包含重复的三元组。
复制代码
例如,给定的数组 S = {-10 0 10 20 -10 -40},解集为(-10, -10, 20),(-10, 0, 10) 

示例1

输入:0

返回值:\[\]

示例2

输入:-2,0,1,1,2

返回值:\[-2,0,2,-2,1,1]

示例3

输入:-10,0,10,20,-10,-40

返回值:\[-10,-10,20,-10,0,10]

分析

这道题重点是去重

代码

java
java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param num int整型一维数组 
     * @return int整型ArrayList<ArrayList<>>
     */
    public ArrayList<ArrayList<Integer>> threeSum (int[] num) {
        // write code here
        ArrayList<ArrayList<Integer>> result=new ArrayList<>();
        Arrays.sort(num);
        for(int i=0;i<num.length;i++){
            if(i>0 && num[i]==num[i-1]){
                continue;
            }
            int left=i+1;
            int right=num.length-1;
            while(left<right){
                int sum=num[i]+num[left]+num[right];
                if(sum>0){
                    right-=1;
                }else if(sum<0){
                    left+=1;
                }else{
                result.add(new ArrayList<>(Arrays.asList(num[i],num[left],num[right])));
                while (right > left && num[right] == num[right - 1]) right--;
                    while (right > left && num[left] == num[left + 1]) left++;
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}
python
python 复制代码
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param num int整型一维数组 
# @return int整型二维数组
#
class Solution:
    def threeSum(self , num: List[int]) -> List[List[int]]:
        # write code here
        num.sort()
        result=[]
        for i in range(len(num)):
            if i>0 and num[i]==num[i-1]:
                continue
            left=i+1
            right=len(num)-1
            while left<right:
                sum=num[i]+num[left]+num[right]
                if sum>0:
                    right-=1
                elif sum<0:
                    left+=1
                else:
                    result.append([num[i],num[left],num[right]])
                    while left<right and num[right]==num[right-1]:
                        right-=1
                    while left<right and num[left]==num[left+1]:
                        left+=1
                    right-=1
                    left+=1
        return result
相关推荐
小雨下雨的雨2 小时前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.5 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
love530love5 小时前
LiveTalking 数字人项目 Windows 部署完全指南(EPGF 架构)
人工智能·windows·python·架构·livetalking·epgf
遇事不決洛必達5 小时前
【Python基础】GIL 锁是什么及其对爬虫的影响
爬虫·python·线程·进程·gil锁
明夜之约5 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee5 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐5 小时前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs5 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
辣机小司5 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
一条小锦吕*5 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化