hash Leetcode 哈希算法题

242.有效的字母异位词

Hash 表

26个英文字母出现的次数记录在一个数组中,再根据s出现的次数在t中判断

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;
        int[] table = new int[26];
        for(int i = 0; i < s.length(); ++ i){
            int ch = s.charAt(i) -'a';
            table[ch] += 1;
        }
        for(int i = 0; i < t.length(); ++ i){
            int ch = t.charAt(i) - 'a';
            table[ch] -= 1;
            if(table[ch] < 0) return false;
        }
        return true;
    }
}

HashMap

getOrDefault() 方法获取指定 key 对应的 value,如果找不到 key 就返回默认值

hashmap.getOrDefault(Object key, V defaultValue)

多态写法:

 Map<Character, Integer> table = new HashMap<>();
class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;
        Map<Character, Integer> table = new HashMap<>();
        for(int i = 0; i < s.length(); ++ i){
            char ch = s.charAt(i);
            table.put(ch, table.getOrDefault(ch, 0) + 1);
        }
        for(int i = 0; i < t.length(); ++ i){
            char ch = t.charAt(i);
            table.put(ch, table.getOrDefault(ch, 0) -1);
            // 没有ch则为-1,多了ch也会为负数
            if(table.get(ch) < 0){
                return false;
            }
        }
        return true;
    }
}

排序

对字符串按照字典序排序,如果排序后两个字符串相等则说明他们包含的字母和次数相同

String 转 char 数组:toCharArray()

char 数组排序:Arrays.sort(char[])

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;
        char[] charS = s.toCharArray();
        char[] charT = t.toCharArray();
        Arrays.sort(charS);
        Arrays.sort(charT);
        return Arrays.equals(charS, charT);
    }
}

我的代码

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()) return false;
        HashMap<Character, Integer> map = new HashMap<>();
        for(int i = 0; i < s.length(); ++ i){
            char ch = s.charAt(i);
            if(map.containsKey(ch)){
                map.put(ch, map.get(ch) + 1);
            }else{
                map.put(ch, 1);
            }
        }
        for(int i = 0; i < t.length(); ++ i){
            char ch = t.charAt(i);
            if(map.containsKey(ch)){
                map.put(ch, map.get(ch) - 1);
            }else{
                return false;
            }
            if(map.get(ch) < 0){
                return false;
            }
        }
        return true;
    }
}

349.两个数组的交集

排序后双指针

两个排序后的数组找他们的公共元素可以用双指针的方式

分别有两个指针指向两个数组,如果这两个指针指向的元素相同,则都前进一步,且比较之前是否已保存过

如果不同,则指向较小的指针前进一步,因为数组是升序排序的,可能小数组的后面有较大的值能与当前另一个数组的较大值相同

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        List<Integer> res = new ArrayList<>();
        int preSame = -1;
        for(int i=0,j=0; i<nums1.length && j< nums2.length;){
            if(nums1[i] == nums2[j]){
                if(nums1[i] != preSame) {
                    preSame = nums1[i];
                    res.add(preSame);
                }
                ++i;
                ++j;
            }else if(nums1[i] < nums2[j]){
                ++i;
            }else{
                ++j;
            }
        }
        int len = res.size();
        int[] ans = new int[len];
        for (int i = 0; i < res.size(); i++) {
            ans[i] = res.get(i);
        }
        return ans;
    }
}

HashSet

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new HashSet<>();
        for (int num : nums1) {
            set1.add(num);
        }
        for (int num : nums2) {
            set2.add(num);
        }

        List<Integer> res = new ArrayList<>();
        for (Integer value : set1) {
            if(set2.contains(value)){
                res.add(value);
            }
        }
        int len = res.size();
        int[] ans = new int[len];
        for (int i = 0; i < res.size(); i++) {
            ans[i] = res.get(i);
        }
        return ans;
    }
}

我的代码

class Solution {
     public int[] intersection(int[] nums1, int[] nums2) {
        List<Integer> res = new ArrayList();
        int[] table = new int[1000];
        for(int i = 0; i < nums1.length; ++ i){
            table[nums1[i]] = 1;
        }
        for(int i = 0; i < nums2.length; ++ i){
            if(table[nums2[i]] == 1){
                res.add(nums2[i]);
                table[nums2[i]] = 0;
            }
        }
        int len = res.size();
        int[] ans = new int[len];
        for (int i = 0; i < res.size(); i++) {
            ans[i] = res.get(i);
        }
        return ans;
    }
}

202.快乐数

观察一个三位的最大数 999,它的每一位平方求和后为 243,并没有越变越大,在经历过足够次数的循环后就会回到原先经历过的数

也就是说会经历一个循环数,需要判断这个循环是1引起的,还是因为不到1而有一个大循环

HashSet 判断循环

public class Solution {
    public boolean isHappy(int n) {
        Set<Integer> table = new HashSet<>();
        while(true){
            int ans = 0;
            while(n != 0){
                int num = n % 10;
                n = n / 10;
                ans = ans + (num * num);
            }
            if(ans == 1){
                return true;
            }
            if(table.contains(ans)){
                return false;
            }
            table.add(ans);
            n = ans;
        }
    }
}

快慢指针判断循环

class Solution {
    public boolean isHappy(int n) {
        int fast = n, slow = n;
        while(true){
            fast = getNext(getNext(fast));
            slow = getNext(slow);
            if(fast == 1){
                return true;
            }else if(fast == slow){
                return false;
            }
        }
    }
    public static int getNext(int n){
        int ans = 0;
        while(n != 0){
            int num = n % 10;
            n /= 10;
            ans += num * num;
        }
        return ans;
    }
}

1.两数之和

从数组中选两个数使其之和等于目标值

先选出一个值,nums[i], 在判断 target-nums[i] 是否存在数组中

可以用hashMap存储除了当前了值的其他值和对应下标

注意这里要前判断是否包含,再加入table中,否则当前值可能会被选两次

class Solution {
public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> table = new HashMap<>();
        for(int i = 0; i < nums.length; ++ i){
            int num = target - nums[i];
            if(table.containsKey(num)){
                return new int[]{i, table.get(num)};
            }
            table.put(nums[i], i);
        }
        return null;
    }
}

我的代码

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> table = new HashMap<>();
        int[] ans = new int[2];
        for(int i = 0; i < nums.length; ++ i){
            if(table.containsKey(target - nums[i])){
                ans[0] = i;
                ans[1] = table.get(target-nums[i]);
                break;
            }
            table.put(nums[i], i);
        }
        return ans;
    }
}

454.四数相加 II

从A,B,C,D 四个数组中各取一个数,使得和为0

最暴力是循环四次,我们可以把数组 D 的值哈希,这样可以 O(1) 判断是否存在值,这样是循环三次

如果将它们分为两组,A,B一组,C,D一组,分别将它们的和哈希,这样只有循环两次

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer, Integer> table = new HashMap<>();
        for(int num1 : nums1){
            for(int num2 : nums2){
                table.put(num1 + num2, table.getOrDefault(num1 + num2, 0) + 1);
            }
        }
        int ans = 0;
        for(int num3 : nums3){
            for(int num4 : nums4){
                ans += table.getOrDefault(-(num3+num4), 0);
            }
        }
        return ans;
    }
}

383.赎金信

ransomNote 能否被 magazine 构成

统计 magazine 里每个字母的个数,遍历 ransomNote,被其中的字母消耗,如果小于0,说明无法构成

这里由于只有26个英文字母,可以用int数组代替Map,速度更快

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        Map<Character, Integer> table = new HashMap<>();
        
        for(int i = 0; i < magazine.length(); ++ i){
            char ch = magazine.charAt(i);
            table.put(ch, table.getOrDefault(ch, 0) + 1);
        }

        for(int i = 0; i < ransomNote.length(); ++ i){
            char ch = ransomNote.charAt(i);
            table.put(ch, table.getOrDefault(ch, 0) - 1);
            if(table.get(ch) < 0){
                return false;
            }
        }
        return true;
    }
}

15.三数之和

排序后双指针

不重复的要求,使得我们必须保证这三个数的顺序是i<j<k的

同时,由于排序后的数组,当 i 固定时,我们可以 O(n) 得到这个数组中是否存在两个数 j,k之和满足目标值的

因为如果小于目标值,说明 j 要增大;
大于目标值,说明 k 要减小;

同时需要剔除相同的数

将多个数转为List集合:List.of(Element e,...)

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        for(int i = 0; i < nums.length; ++i){
            if(i > 0 && nums[i] == nums[i-1]) continue;
            int j = i + 1, k = nums.length - 1;
            while(j < k){
                int sum = nums[i] + nums[j] + nums[k];
                if(sum < 0) ++j;
                else if(sum > 0) --k;
                else{
                    ans.add(List.of(nums[i], nums[j], nums[k]));
                    ++j;
                    --k;
                    while(nums[j] == nums[j-1] && j < k) ++j;
                    while(nums[k] == nums[k+1] && j < k) --k;
                }
            }
        }
        return ans;
    }
}

18.四数之和

与三数之和相同,遍历前n-2个数,后两个数用双指针

由于数组时升序的,所以有优化之处:

  1. 当第i个数开始的最小四元组:i + (i+1) + (i+2) + (i+3)>target后,最小的都大,则后面的越来越大,就不可能出现等于target的四元组了
  2. 当第i个数开始的最大四元组:i + (n-3) + (n-2) + (n-3)<target后,最大的都小,则这个i选得太小,后面的遍历不用看了,直接让i++,第一个数变大一点才有可能等于target

注意:

  1. 要用 n-3,n-2提前限制下标,否则四个数相加会超出下标
  2. 数据会超过 int,需要强转为 long
  3. 注意判断 j 时,i 已经固定了,所以最大最小四元组的计算有一些改变
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        for(int i = 0; i < n - 3; ++ i){
            if(i > 0 && nums[i] == nums[i-1]) continue;
            if((long) nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) break;
            if((long) nums[i] + nums[n-3] + nums[n-2] + nums[n-1] < target) continue;
            for(int j = i + 1; j < n - 2; ++ j){
                if(j > i + 1 && nums[j] == nums[j-1]) continue;
                if((long) nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) break;
                if((long) nums[i] + nums[j] + nums[n-2] + nums[n-1] < target) continue;
                int k = j + 1, z = n - 1;
                while(k < z){
                    long sum = (long) nums[i] + nums[j] + nums[k] + nums[z];
                    if(sum < target) ++k;
                    else if(sum > target) --z;
                    else{
                        ans.add(List.of(nums[i], nums[j], nums[k], nums[z]));
                        ++k;
                        --z;
                        while(k < z && nums[k] == nums[k-1]) ++k;
                        while(k < z && nums[z] == nums[z+1]) --z;
                    }
                }
            }
        }
        return ans;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3+elment复杂详情页面打开后,再打开其他页面都显示空白,控制台也没什么特殊报错

页面使用了el-tabs 、 el-tab-pane、el-table 等标签 但是经测试不是这些问题导致的 js也使用了onMounted &#xff0c;但是除掉也时空白页面 反正之前人写的页面可乱&#xff0c;尤其是js这块&#xff0c;穿插引用import一大堆 主题页面样式布局如下 最后看到页面代码太乱…

古籍数字化平台:精校功能介绍

一、平台介绍 古籍数字化平台&#xff0c;本着公益性、低成本、合作共赢的三大原则&#xff0c;功能涵盖古籍OCR识别、族谱县志OCR识别、民国报纸OCR识别、图文逐字校对、数据著录、智能标点分段、精编排版、智能白话译文等&#xff0c;是一站式线上整理全流程平台。 平台集成…

备战面试K8S

备战面试&&K8S Kubernetes关于DockerDocker的优缺点分析 WebAssemblyWebAssembly与Container比较 CtrCrictlCtr和CriCtl的区别 Pod生命周期PodConditions容器状态Pod容器组成生命周期的流程 Kubelet EFK日志采集工具的优缺点 Kubernetes 容器运行接口 Container Runti…

2024年免费云服务器推荐,小编亲测好用!

随着云计算技术的飞速发展&#xff0c;云服务器以其弹性、高效、安全的特性&#xff0c;成为众多企业和个人用户的首选。尽管市面上有众多收费的云服务器产品&#xff0c;但免费的云服务器仍然吸引着大量用户&#xff0c;尤其是初学者和预算有限的用户。下面&#xff0c;我们就…

从API到Agent:洞悉LangChain工程化设计

作者&#xff1a;范志东 原文&#xff1a;https://mp.weixin.qq.com/s/zGS9N92R6dsc9Jk57pmYSg 本文作者试着从工程角度去理解LangChain的设计和使用。大家可以将此文档作为LangChain的“10分钟快速上手”手册&#xff0c;希望帮助需要的同学实现AI工程的Bootstrap。 我想做一…

[Vision Board创客营]学习片上Flash移植FAL

文章目录 [Vision Board创客营]学习片上Flash移植FAL介绍环境搭建使用组件测试porbeerasewriteread 结语 [Vision Board创客营]学习片上Flash移植FAL 水平较菜&#xff0c;大佬轻喷。&#x1f630;&#x1f630;&#x1f630; 介绍 &#x1f680;&#x1f680;Vision-Board 开…

安全开发实战(3)--存活探测与端口扫描

目录 安全开发专栏 前言 存活探测 端口扫描 方式一: 1.3.1 One 1.3.2 Two 1.3.3 批量监测 方式二: 1.3.1 One 1.3.2 Two 1.3.3 Three 1.3.4 扫描ip地址,提取出开放端口和协议 ​编辑 1.3.5 批量扫描(最终完成版) 总结 安全开发专栏 安全开发实战​http://t.csd…

MySql数据库从0-1学习-第五天事务和索引

事务 事务 是一组操作的集合&#xff0c;它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作 要么同时成功&#xff0c;要么同时失败。 注意事项,默认事务是自动提交的,也就是说,当执行一条DML语句,MySql会立即隐…

【Java开发指南 | 第八篇】Java变量、构造方法、创建对象

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 Java变量构造方法创建对象 Java变量 在Java中&#xff0c;变量用于存储数据值。它们是程序中用于保存信息的一种基本方式。变量在程序执行过程中可以被赋予不同的值&#xff0c;并且这些值可以在程序的不同部分…

超越现实的展览体验,VR全景展厅重新定义艺术与产品展示

随着数字化时代的到来&#xff0c;VR全景展厅成为了企业和创作者展示作品与产品的新兴选择。通过结合先进的虚拟现实技术&#xff0c;VR全景展厅不仅能够提供身临其境的观展体验&#xff0c;而且还拓展了传统展示方式的界限。 一、虚拟现实技术的融合之美 1、高度沉浸的观展体验…

Unity开发holoLens2应用时的ProjectSettings配置

正确的进行Unity工程配置&#xff0c;才能进行后续的【发布】和【部署】操作… 本案例开发环境说明&#xff1a; Unity2021.3.18Win10VS2022HoloLens2 一、平台设置 二、Quality画面质量设置 三、Player玩家设置 四、XR-Plug设置 五、环境测试 导入一个官方demo&#xff0c…

EasyPoi表格导入添加校验

EasyPoi表格导入添加校验 项目添加maven依赖实体类自定义校验controller测试结果 代码地址 项目添加maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www…

【任务调度】Apache DolphinScheduler快速入门

Apache DolphinScheduler基本概念 概念&#xff1a;分布式、去中心化、易扩展的可视化DAG工作流任务调度系统。 作用&#xff1a;解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。Apache DolphinScheduler是一款开源的调度工具&#xff…

紫光展锐携手中国联通智慧矿山军团(山西)完成RedCap现网环境测试

近日&#xff0c;紫光展锐与中国联通智慧矿山军团&#xff08;山西&#xff09;在现网环境下成功完成了RedCap技术测试。此次测试对搭载紫光展锐RedCap芯片平台V517的模组注网速度和信号情况、Iperf打流测试上下行情况、ping包延时情况以及模组拨号入网压测等项目进行了全面验证…

OpenHarmony UI动画-rebound

简介 rebound是一个模拟弹簧动力学&#xff0c;用于驱动物理动画的库。 下载安装 ohpm install ohos/reboundOpenHarmony ohpm环境配置等更多内容&#xff0c;请参考如何安装OpenHarmony ohpm 使用说明 import rebound from ohos/rebound;功能一&#xff1a;创建维护弹簧对…

韩顺平Java | C27 正则表达式

入门介绍 需求&#xff1a;提取文本中某类字符 传统方法&#xff1a;遍历每个字符&#xff0c;判断其是否在ASCII码中某种类型得编码范围内&#xff0c;代码量大&#xff0c;效率不高 正则表达式(RegExp, regular expression)&#xff1a;处理文本的利器&#xff0c;是对字符…

【详细介绍下图搜索算法】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

Golang入门基础

文章目录 Golang的背景知识Golang的发展历程Golang的特点Golang的应用领域 开发环境搭建下载并安装SDK包设置环境变量Go项目目录结构 注释变量标识符命名输入和输出运算符算术运算符关系运算符逻辑运算符赋值运算符位运算符其他运算符 Golang的背景知识 Golang的发展历程 Gola…

高仿小米商城用户端

高仿小米商城用户端(分为商城前端&#xff08;tongyimall-vue)和商城后端(tongyimall-api)两部分)&#xff0c;是Vue SpringBoot的前后端分离项目&#xff0c;用户端包括首页门户、商品分类、首页轮播、商品展示、商品推荐、购物车、地址管理、下订单、扫码支付等功能模块。 …

Docker Volume (存储卷)

什么是存储卷? 存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着&#xff0c;当我们在容器中的这个目录下写入数据时&#xff0c;容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。在宿主机上…
最新文章