LeetCode_Day6 | 有效的字母异位词、两个数组的交集、快乐数、两数之和!

news2024/11/24 8:58:47

LeetCode_哈希表

  • 242.有效的字母异位词
    • 1.题目描述
    • 2.题解
  • 349.两个数组的交集
    • 1.题目描述
    • 2.题解
  • 202.快乐数
    • 1.题目描述
    • 2.题解
      • 思路(官方题解啊!看了好几遍真难)
    • 3.算法
    • 4.代码实现
    • 5.复杂度分析
  • 1.两数之和
    • 1.题目描述
    • 2.哈希表法
    • 3.代码实现

242.有效的字母异位词

1.题目描述

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例:
输入: s = “anagram”, t = “nagaram”
输出: true

输入: s = “rat”, t = “car”
输出: false

详情leetcode链接

2.题解

先看思路哦!

class Solution {
    /**
     * 思路:需要一个额外的数组记录两个字符串每个字母出现的次数,一个次数增加,
     *       一个次数减少;若最后每个数组上每个数字都中和为0则为字母异位词。
     *     1.因为都是小写字母,所以需要定义一个数组record来记录每个字母出现的次数;
     *     2.因为字符a到字符z的ASCII也是26个连续的数,所以数组大小为 26,初始化为0;
     *     3.需要把字符映射到数组也就是哈希表的索引下标上:因为字符a到字符z的ASCII是
     *  26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
     *     4.再遍历 字符串s的时候,只需要将 s[i] - ‘a’、‘b’等所在的元素做+1 操,同
     *  样在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。 
     *     5.最后record数组如果有的元素不为零0,即字符串s和t一定是谁多了字符或者谁少
     *  了字符,return false。若record数组所有元素都为零0,说明字符串s和t是字母异位
     *  词,return true。
     * 时间复杂度:O(m+n),分别遍历了字符串s和t,长度设为 m 和 n(补充:因为数组长度与输入参数无关且为常量可看作O(1)可忽略不计,这里的m和n是和输入字符串长度有关,所以为m+n)
     * 空间复杂度:O(1)
     *     
     *
     */
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];
		//例如字符串s="aee",字符串t="eae"
		//s.charAt(a)-'a'=0,即recored数组的第一个位置,刚好与a~z相映射
        for (int i = 0; i < s.length(); i++){
            record[s.charAt(i)-'a']++; //charAt()即返回指定索引处的字符,举例字符a返回97。并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
        }

        for (int i = 0; i < t.length(); i++){
            record[t.charAt(i)-'a']--;
        }

        for (int count : record){
            if (count != 0){  // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }

        return true; // record数组所有元素都为零0,说明字符串s和t是字母异位词
    }
}

349.两个数组的交集

1.题目描述

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 :
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

详情leetcode链接

2.题解

先看思路哦!

class Solution {

    /**
     * 思路:哈希set
     *      题目中提到输出结果中的每个元素一定是唯一的,即输出的结果的去重的, 同时可以不考虑输出结果的顺序,所以用哈希set做比较合适
     *      首先遍历数组nums1,将nums1映射到set1中。
     *      接着遍历数组2的过程中判断哈希表set1中是否存在该元素,若存在则放到reSet(用于返回的set)中,最后将结果集转为数组返回。
     * 注意:此题也可以使用数组来做哈希的题目,是因为题目都限制了数值的大小。如果本题没有限制数值的大小,就无法使用数组来做哈希表了。
     * 时间复杂度:O(m + n):假设数组nums1长度为m,nums长度为n。分别遍历
     * 空间复杂度:O(m): 定义了两个set,其大小取决于nums的大小
     *
     */
    public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> reSet = new HashSet<>();
        //遍历nums1映射到set1
        for (int i: nums1) {
            set1.add(i);
        }

        //遍历nums2过程中判断set1中是否存在该元素,存在放到reSetzh
        for (int i : nums2){
            if (set1.contains(i)){
                reSet.add(i);
            }
        }

        //将结果集转为数组返回
        return reSet.stream().mapToInt(x->x).toArray();

        // //方法2:将结果集转为数组返回
        // int[] array = new int[reSet.size()];
        // int j = 0;
        // for (int i : reSet){
        //     array[j++] = i;
        // }
        // return array;

    }
}

202.快乐数

1.题目描述

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:
输入:n = 2
输出:false

详情leetcode链接

2.题解

思路(官方题解啊!看了好几遍真难)

  • 根据题意确定边界:(1)最终会得到1;(2)最终会进入循环

  • 举例1,例如7——>72=49——>42+92=97…(不断循环此过程),如图直到1
    在这里插入图片描述

  • 举例2,从 116开始。通过反复通过平方和计算下一个数字,我们最终得到 58,再继续计算之后,我们又回到 58。由于我们回到了一个已经计算过的数字,可以知道有一个循环,因此不可能达到 1。
    在这里插入图片描述

  • 所以根据穷举,猜测会有以下三种可能。
    最终会得到 11。
    最终会进入循环。
    值会越来越大,最后接近无穷大。

  • 对于第三种情况的思考:我们怎么知道它会继续变大,而不是最终得到 1 呢?可以仔细想一想,每一位数的最大数字的下一位数是多少。
    在这里插入图片描述

  • 对于 3位数的数字,它不可能大于 243。这意味着它要么被困在 243以下的循环内,要么跌到 1。4 位或 4 位以上的数字在每一步都会丢失一位,直到降到 3 位为止。所以我们知道 最坏的情况下,算法可能会在 243 以下的所有数字上循环,然后回到它已经到过的一个循环或者回到 1。但它不会无限期地进行下去,所以我们排除第三种选择。

3.算法

算法分为两部分,我们需要设计和编写代码。

  1. 给一个数字 n,它的下一个数字是什么?
  2. 按照一系列的数字来判断我们是否进入了一个循环。

第 1 部分我们按照题目的要求做数位分离,求平方和。

第 2 部分可以使用哈希集合完成。每次生成链中的下一个数字时,我们都会检查它是否已经在哈希集合中。
如果它不在哈希集合中,我们应该添加它。
如果它在哈希集合中,这意味着我们处于一个循环中,因此应该返回 false。

注意: 我们使用哈希集合而不是向量、列表或数组的原因是因为我们反复检查其中是否存在某数字。检查数字是否在哈希集合中需要 O(1)的时间,而对于其他数据结构,则需要 O(n)的时间。

4.代码实现

/**
 * 202.快乐数
 * 1)给定一个数n,获取下一个数是什么?
 * 2)按照一系列的数字来判断我们是否进入了一个循环
 * 时间复杂度:O(logn)
 * 空间复杂度:O(logn)
 */
class Solution {

    public static int getNext(int n){
        int totalSum = 0;
        while (n>0){
            int d = n % 10;//取余数获得个位上的数字
            n = n / 10;//取商获得十位上的数字
            totalSum += d*d;
        }
        return totalSum;
    }

    public static boolean isHappy(int n){
        Set<Integer> seen = new HashSet<>();//利用set判断重复
        while (n != 1 &&  !seen.contains(n)){
            seen.add(n);
            n = getNext(n);
        }
        return n==1;
    }
}

5.复杂度分析

时间复杂度: O(243 *3 + log n + loglog n + logloglog n+…) = O(log n)

假设最坏情况,假设小于243的数把每一个数都取到了,那也就是243次判断,每次判断小于3次(因为是三位数以下),所以计算小于243的数的时间复杂度大O是:O(243∗3)

而对于大于243的数,计算下一个数的时间复杂度是:O(log10n)
因为我们正在处理数字中的每位数字,而数字中的位数由 logn 给定。

要计算出总的时间复杂度,我们需要仔细考虑循环中有多少个数字,它们有多大。

我们在上面确定,一旦一个数字低于 243,它就不可能回到 243以上。因此,我们就可以用 243 以下最长循环的长度来代替 243,不过,因为常数无论如何都无关紧要,所以我们不会担心它。

对于高于 243的 n,我们需要考虑循环中每个数高于 243 的成本。通过数学运算,我们可以证明在最坏的情况下,这些成本将是 O(log n) + O(loglog n) + O(logloglog n)…。幸运的是,O(logn) 是占主导地位的部分,而其他部分相比之下都很小(总的来说,它们的总和小于logn),所以我们可以忽略它们。

空间复杂度: O(logn)。

与时间复杂度密切相关的是衡量我们放入哈希集合中的数字以及它们有多大的指标。对于足够大的 n,大部分空间将由 n本身占用。我们可以很容易地优化到 O(243 * 3) = O(1),方法是只保存集合中小于 243 的数字,因为对于较高的数字,无论如何都不可能返回到它们。

1.两数之和

1.题目描述

在这里插入图片描述
详情leetcode链接

2.哈希表法

本题看似简单,实则不简单!思考时主要有以下几个重点:

  • 为什么会想到用哈希表?
  • 哈希表为什么用map
  • 本题map是用来存什么的
  • map中的key和value用来存什么的

回忆什么时候使用哈希法: 当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

本题呢,我就需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。

此时我们就应该想到使用哈希法了。

根据题意,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。

再来看一下使用数组和set来做哈希法的局限。

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。

此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

3.代码实现

class Solution {
    /**
     *哈希表法
     *时间复杂度:O(n)
     *空间复杂度:O(n)
     */
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        if(nums == null || nums.length == 0){
           return result;
        }
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0;i<nums.length;i++){
            //遍历当前元素,并在map中寻找是否有匹配的key
            int temp = target - nums[i];
            if (map.containsKey(temp)){
                result[1] = i;
                result[0] = map.get(temp);
                break;
            }else {
                map.put(nums[i],i);
            }
        }
        return result;
    }
}

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

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

相关文章

《三》TypeScript 中函数的类型

TypeScript 允许指定函数的参数和返回值的类型。 函数声明的类型定义&#xff1a;function 函数名(形参: 形参类型, 形参: 形参类型, ...): 返回值类型 {} function sum(x: number, y: number): number {return x y } sum(1, 2) // 正确 sum(1, 2, 3) // 错误。输入多余的或者…

CAN总线竞争与仲裁机制分析

1、CAN总线的接口 (1)CAN总线是串行、差分信号、异步总线&#xff0c;传输数据用两根信号线组成的差分信号线&#xff1b; (2)CANH和CANL是一组双绞线&#xff0c;两根线的电平差值表示逻辑1和0&#xff1b; 2、CAN总线显性、隐形电平 显性电平代表逻辑0&#xff0c;隐形电平代…

【Prometheus】mysqld_exporter+Grafana+AlertManager预警

环境 prometheus-2.44.0 mysqld_exporter-0.14.0 grafana-enterprise-9.1.2-1.x86_64.rpm alertmanager-0.25.0. 简介 mysql_exporter是用来收集MysQL或者Mariadb数据库相关指标的&#xff0c;mysql_exporter需要连接到数据库并有相关权限。既可以用二进制安装部署&#xff0c;…

08.JavaWeb-SpringMVC

2.SpringMVC Spring框架是一个开源的轻量级框架&#xff0c;SpringMVC是Spring的一个子框架 2.1SpringMVC工作机制 2.1.1 DispatcherServlet前端控制器 【不需要程序员开发】 作用&#xff1a;作为接受请求&#xff0c;响应结果&#xff0c;相当于转发器&#xff0c;中央处理…

『Jenkins』最新版Jenkins安装与Git集成—CentOS 7安装的详细教程

&#x1f4e3;读完这篇文章里你能收获到 图文形式安装Jenkins在Jenkins集成Git并进行的配置感谢点赞收藏&#xff0c;避免下次找不到~ 文章目录 一、准备工作1. 安装Java Development Kit (JDK 11) 二、安装Jenkins1. 下载和安装最新版的Jenkins2. 启动Jenkins服务3. 将Jenkin…

【线性代数】

求解线性方程组 右乘向量/矩阵 把左边的矩阵拆成一个个列向量&#xff0c;右边的向量表示对左边列向量组的线性组合。 [ c o l 1 c o l 2 c o l 3 ] [ 3 4 5 ] [ 3 c o l 1 4 c o l 2 5 c o l 3 ] \left[\begin{array}{c} col_{1} & col_{2} & col_{3} \end{array}\…

类的三大特性——>封装

目录 理论知识 数据抽象&#xff1a; 封装&#xff1a; 细节知识 访问控制与封装 访问控制 STL使用封装 理论知识 类的基本思想是数据抽象、和封装。 数据抽象&#xff1a; 是一种依赖接口和实现分离的一种编程技术&#xff1a; 接口&#xff1a;包括用户所能执行的操…

点燃创作灵感:Prompt 实践指南揭秘!让 ChatGPT 更智能的六种策略(上)

在和 ChatGPT 对话中&#xff0c;Prompt 提示词的选择&#xff0c;如果遵循以下六种策略&#xff0c;我们将获得更好、更符合要求的回答。 这些策略&#xff0c;后几种更适合在编程调用 ChatGPT API 时使用&#xff0c;不过也适用直接和 ChatGPT 对话&#xff0c;让它更好的理解…

【LeetCode】HOT 100(7)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

C语言之基于链表实现排序

题目&#xff1a;通过链表实现从小到大进行排序 代码&#xff1a; #include <stdio.h> #include <stdlib.h> #define N 9//通过链表实现从小到大排序 typedef struct node {int data;struct node *next; } NODE;//fun函数实现是将头结点的单向链表节点…

chatgpt赋能python:Python怎么倒序输出中文字典?

Python怎么倒序输出中文字典&#xff1f; 作为一门高效、易上手的编程语言&#xff0c;Python在数据处理、科学计算、机器学习等领域都有广泛应用。而对于SEO工程师来说&#xff0c;Python也是一款非常实用的工具。那么今天&#xff0c;我们就来探讨一下Python怎么倒序输出中文…

Sqlite 比较,安装,使用,个人总结

文章目录 什么是sqlite&#xff0c;和别的数据库有什么差别&#xff1f;sqlite介绍什么是边缘存储&#xff1f; sqlite存储上限sqlite和别的数据库的区别 Sqlite本地安装sqlite 在C# .net webapi 软件中的使用 什么是sqlite&#xff0c;和别的数据库有什么差别&#xff1f; sq…

【JavaSE】Java(五十七):核心要点总结

文章目录 1. HashMap 的实现原理2. Set 有哪些实现类3. HashSet 的实现原理4. 如何实现数组和List之间的转换5. Java中的迭代器 1. HashMap 的实现原理 HashMap 是一种基于哈希表的数据结构&#xff0c;它的实现原理简单来说就是将键值对存储在一个数组中&#xff0c;并通过哈希…

深入理解深度学习——注意力机制(Attention Mechanism):自注意力(Self-attention)

分类目录&#xff1a;《深入理解深度学习》总目录 相关文章&#xff1a; 注意力机制&#xff08;AttentionMechanism&#xff09;&#xff1a;基础知识 注意力机制&#xff08;AttentionMechanism&#xff09;&#xff1a;注意力汇聚与Nadaraya-Watson核回归 注意力机制&#…

强化服务器安全!CentOS 7如何使用fail2ban防范SSH暴力破解攻击?

前言 本文主要讲解centos7操作系统下&#xff0c;如何使用fail2ban防范SSH暴力破解。 &#x1f3e0;个人主页&#xff1a;我是沐风晓月 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是沐风晓月&#xff0c;阿里云社区博客专家 &#x1f609;&#x1f609; &#x1…

如何使用Python生成跑马灯视频

在这篇博客中&#xff0c;我将向您展示如何使用Python语言生成一个简单的跑马灯视频。我们将使用OpenCV和Pillow两个库来实现这个功能。 安装依赖库 首先&#xff0c;我们需要安装opencv-python和Pillow两个库。您可以使用以下命令来安装它们&#xff1a; pip install opencv…

Navicat 设置PostgreSQL数据库的表主键ID自增

文章目录 1 新建序列1.1 手动新建1.2 SQL语句新建 2 设置主键自增 1 新建序列 1.1 手动新建 选择 其他->序列 选择一个模式&#xff08;例如public&#xff09;&#xff0c;然后选择新增序列。 设置序列参数 刷新序列列表即可看到新建的序列 注意&#xff1a; 序列的最大…

C语言实现2048小游戏

大部分同学学习C语言编程以后不知道能通过什么样的项目才可以锻炼自己的思维功力&#xff0c;2048相信大家都应该熟悉&#xff0c;不管是手机上还是网页版的相信大家都玩过,这个简单的控制台版本的游戏是我曾经在伟易达上班时一个嵌入式应用游戏部门的大佬设计的&#xff0c;适…

简单使用gateway,以及gateway所需要的依赖

先声明&#xff0c;使用gateway需要有一定的SpringCloud的基础&#xff0c;再来使用时会看的很明白&#xff0c;使用前需要先开nacos服务&#xff0c;&#xff0c;确定无误。 下面直接开始 首先我们需要两个原来通信的模块&#xff0c;这里分别是service-const与service-provid…

《导航帖》-全系列软考A计划

专栏分享 点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 文章目录 &#x1f449;关于作者&#x1f449;前提&#x1f449;链接追踪&#x1f449…