算法刷题-哈希表-有效的字母异位词

news2024/11/19 3:17:45

有效的字母异位词

    • 242.有效的字母异位词
    • 思路
    • 其他语言版本
    • 相关题目

数组就是简单的哈希表,但是数组的大小可不是无限开辟的

242.有效的字母异位词

力扣题目链接

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

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

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

说明:
你可以假设字符串只包含小写字母。

思路

先看暴力的解法,两层for循环,同时还要记录字符是否重复出现,很明显时间复杂度是 O(n^2)。

暴力的方法这里就不做介绍了,直接看一下有没有更优的方式。

数组其实就是一个简单哈希表,而且这道题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数。

需要定义一个多大的数组呢,定一个数组叫做record,大小为26 就可以了,初始化为0,因为字符a到字符z的ASCII也是26个连续的数值。

为了方便举例,判断一下字符串s= “aee”, t = “eae”。

操作动画如下:

在这里插入图片描述

定义一个数组叫做record用来上记录字符串s里字符出现的次数。

需要把字符映射到数组也就是哈希表的索引下标上,因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。

再遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了。

那看一下如何检查字符串t中是否出现了这些字符,同样在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。

那么最后检查一下,record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。

最后如果record数组所有元素都为零0,说明字符串s和t是字母异位词,return true。

时间复杂度为O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为O(1)。

C++ 代码如下:

class Solution {
public:
    bool isAnagram(string s, string t) {
        int record[26] = {0};
        for (int i = 0; i < s.size(); i++) {
            // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
            record[s[i] - 'a']++;
        }
        for (int i = 0; i < t.size(); i++) {
            record[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (record[i] != 0) {
                // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }
        // record数组所有元素都为零0,说明字符串s和t是字母异位词
        return true;
    }
};

其他语言版本

Java:

/**
 * 242. 有效的字母异位词 字典解法
 * 时间复杂度O(m+n) 空间复杂度O(1)
 */
class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];

        for (int i = 0; i < s.length(); i++) {
            record[s.charAt(i) - 'a']++;     // 并不需要记住字符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是字母异位词
    }
}

Python:

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        record = [0] * 26
        for i in s:
            #并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
            record[ord(i) - ord("a")] += 1
        for i in t:
            record[ord(i) - ord("a")] -= 1
        for i in range(26):
            if record[i] != 0:
                #record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return False
        return True

Python写法二(没有使用数组作为哈希表,只是介绍defaultdict这样一种解题思路):

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import defaultdict
        
        s_dict = defaultdict(int)
        t_dict = defaultdict(int)

        for x in s:
            s_dict[x] += 1
        
        for x in t:
            t_dict[x] += 1

        return s_dict == t_dict

Python写法三(没有使用数组作为哈希表,只是介绍Counter这种更方便的解题思路):

class Solution(object):
    def isAnagram(self, s: str, t: str) -> bool:
        from collections import Counter
        a_count = Counter(s)
        b_count = Counter(t)
        return a_count == b_count

Go:

func isAnagram(s string, t string) bool {
    record := [26]int{}
    
    for _, r := range s {
        record[r-rune('a')]++
    }
    for _, r := range t {
        record[r-rune('a')]--
    }

    return record == [26]int{}   // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
}

javaScript:

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if(s.length !== t.length) return false;
    const resSet = new Array(26).fill(0);
    const base = "a".charCodeAt();
    for(const i of s) {
        resSet[i.charCodeAt() - base]++;
    }
    for(const i of t) {
        if(!resSet[i.charCodeAt() - base]) return false;
        resSet[i.charCodeAt() - base]--;
    }
    return true;
};

TypeScript:

function isAnagram(s: string, t: string): boolean {
    if (s.length !== t.length) return false;
    let helperArr: number[] = new Array(26).fill(0);
    let pivot: number = 'a'.charCodeAt(0);
    for (let i = 0, length = s.length; i < length; i++) {
        helperArr[s.charCodeAt(i) - pivot]++;
        helperArr[t.charCodeAt(i) - pivot]--;
    }
    return helperArr.every(i => i === 0);
};

Swift:

func isAnagram(_ s: String, _ t: String) -> Bool {
    if s.count != t.count {
        return false
    }
    var record = Array(repeating: 0, count: 26)
    let aUnicodeScalar = "a".unicodeScalars.first!.value
    for c in s.unicodeScalars {
        record[Int(c.value - aUnicodeScalar)] += 1
    }
    for c in t.unicodeScalars {
        record[Int(c.value - aUnicodeScalar)] -= 1
    }
    for value in record {
        if value != 0 {
            return false
        }
    }
    return true
}

PHP:

class Solution {
    /**
     * @param String $s
     * @param String $t
     * @return Boolean
     */
    function isAnagram($s, $t) {
        if (strlen($s) != strlen($t)) {
            return false;
        }
        $table = [];
        for ($i = 0; $i < strlen($s); $i++) {
            if (!isset($table[$s[$i]])) {
                $table[$s[$i]] = 1;
            } else {
                $table[$s[$i]]++;
            }
            if (!isset($table[$t[$i]])) {
                $table[$t[$i]] = -1;
            } else {
                $table[$t[$i]]--;
            }
        }
        foreach ($table as $record) {
            if ($record != 0) {
                return false;
            }
        }
        return true;
    }
}

Rust:

impl Solution {
    pub fn is_anagram(s: String, t: String) -> bool {      
        let mut record = vec![0; 26];
        
        let baseChar = 'a';
        
        for byte in s.bytes() {
            record[byte as usize - baseChar as usize] += 1;
        } 
        for byte in t.bytes() {
            record[byte as usize - baseChar as usize] -= 1;
        } 

        record.iter().filter(|x| **x != 0).count() == 0
    }
}

Scala:

object Solution {
  def isAnagram(s: String, t: String): Boolean = {
    // 如果两个字符串的长度不等,直接返回false
    if (s.length != t.length) return false
    val record = new Array[Int](26) // 记录每个单词出现了多少次
    // 遍历字符串,对于s字符串单词对应的记录+=1,t字符串对应的记录-=1
    for (i <- 0 until s.length) {
      record(s(i) - 97) += 1
      record(t(i) - 97) -= 1
    }
    // 如果不等于则直接返回false
    for (i <- 0 until 26) {
      if (record(i) != 0) {
        return false
      }
    }
    // 如果前面不返回false,说明匹配成功,返回true,return可以省略
    true
  }
}

C#:

 public bool IsAnagram(string s, string t) {
         int sl=s.Length,tl=t.Length;
        if(sl!=tl) return false;
        int[] a = new int[26];
        for(int i = 0; i < sl; i++){
             a[s[i] - 'a']++;
             a[t[i] - 'a']--;
        }       
        foreach (int i in a)
        {
            if (i != 0)
                return false;
        }
        return true;
    }

相关题目

  • 383.赎金信
  • 49.字母异位词分组
  • 438.找到字符串中所有字母异位词

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

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

相关文章

对数据进行模糊匹配搜索(动态规划、最长公共子串、最长公共子序列)

在搜索时常常在输入一半或者输入错误时&#xff0c;搜索引擎就给出智能提示。 已知的搜索推荐主要包括以下几个方面&#xff1a; 包含&#xff1a;“清华” 和 “清华大学”相似&#xff1a;“聊天软件” 和 “通讯软件”相关&#xff1a;“明星” 和 “刘亦菲”纠错&#xff…

Uni-app学习从0到1开发一个app——(4)生命周期

文章目录 0 引入1、应用生命周期2、页面生命周期3、组件生命周期4、引用 0 引入 uin-app生命周期是以小程序的生命周期为基础实现的&#xff0c;分为应用生命周期、页面生命周期、和组件生命周期&#xff0c;其中组件生命周期就是Vue的生命周期。 官方文档可见&#xff1a;ht…

java之反射机制和注解(更新中......)

Reflect在文档中的位置&#xff1a; 文档链接&#xff1a;https://docs.oracle.com/javase/8/docs/api/index.html 用于获取类或对象的反射信息。 常用的反射机制重要的类&#xff1a; java.lang.Class&#xff1a;整个字节码&#xff0c;代表一个类型。包含了以下三块内容&a…

算法刷题-了解哈希表

哈希表 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 哈希表是根据关键码的值而直接进行访问的数据结构。 这么这官方的解释…

Spring Boot 基本配置

大家好&#xff01;我是今越。简单记录一下在 Spring Boot 中的一些基本配置。 Banner 配置 配置文件 application.properties # 设置路径和名称&#xff0c;默认路径名称 resources/banner.txt spring.banner.locationclasspath:banner1.txt # 启动项目时&#xff0c;关闭 b…

语法篇JQuery基础

目录 一、初识JQuery 1.1JQuery介绍 导入方式 常用公式 1.2快速入门 二、JQuery入门 2.1文档就绪函数 2.2名称冲突 2.3JQuery选择器 表单选择器 2.4JQuery过滤器 基础过滤器(Basic Fiter) 子元素过滤器 内容过滤器 可见性过滤器 三、JQuery事件与特效 3.1JQuery…

set/map学习

我们要开始学习map和set的使用&#xff0c;虽然使用更加复杂&#xff0c;但是STL整体的设计&#xff0c;本身就具有很强的前瞻性和延续性&#xff0c;比如说迭代器等&#xff0c;我们顺着文档来看。这也是除了vector之外最重要的容器&#xff0c;当然还有unordered_map 和 unor…

g++ 编译选项

1&#xff0c;基本编译过程 g可以用于编译C代码生成可执行程序&#xff0c;从原始代码到生成可执行过程中实际经历了以下4个步骤&#xff1a; 1. 预处理&#xff1a;宏替换&#xff0c;注释消除&#xff0c;查找相关库文件等[使用-E参数]。 # 只激活预处理&#xff0c;不会自…

集成正态云和动态扰动的哈里斯鹰优化算法(IHHO)-附代码

集成正态云和动态扰动的哈里斯鹰优化算法(IHHO) 文章目录 集成正态云和动态扰动的哈里斯鹰优化算法(IHHO)1.哈里斯鹰优化算法2.改进哈里斯鹰优化算法2.1 正态云模型2.2 随机反向学习思想2.3 动态扰动策略 3.实验结果4.参考文献5.Matlab代码6.python代码 摘要&#xff1a; 针对基…

Uni-app学习从0到1开发一个app——(3)简单小工程内容介绍

文章目录 工程文件 看看一个标准的hello微信小程序工程文件的组成和作用。 工程文件 可以参考官方教程&#xff1a;传送门 之前的文章有详细的开发环境介绍&#xff0c;传送门Uni-app学习从0到1开发一个app——(2)windowns环境搭配&#xff0c;这里我们先建一个简单的示例微信…

【工具】Xshell-7和Xftp-7下载安装使用教程

目录 一、Xshell和Xftp 二、安装包下载(Xshell和Xftp) 三、Xshell安装、使用和常用设置 1. Xshell安装&#xff1a; 2. Xshell使用: 3. Xshell常用设置 三、Xftp安装、使用 1. Xftp安装 2. Xftp使用 一、Xshell和Xftp Xshell&#xff1a; Xshell是一款强大的SSH&#xff…

【数据结构与算法分析】树上漫步之探究前序、中序、后序、广度优先遍历算法的实现与优化

文章目录 前言二叉树的遍历方式构建二叉树递归遍历二叉树非递归遍历二叉树层次遍历 示例二叉树结果总结 前言 二叉树是数据结构中最基本的数据结构之一&#xff0c;它在计算机科学中有着非常重要的应用。二叉树的遍历是指按照一定的顺序遍历二叉树中的所有节点&#xff0c;是二…

DML——数据库查询语言

查询——select SELECT [DISTINCT/ALL/] {*|column|expression [alias],…} FROM table [Natuarl join /] where子句; Natuarl join 自然连接只考虑那些在两个关系模式中都出现的属性上取值相同的元祖队。 列名&#xff08;属性名&#xff09;完成相同值相同去除重复列拓展&…

【Typora+Lsky】在deepin使用YGXB-net/lsky-upload上传图片

本文首发于 慕雪的寒舍 在win和deepin上使用lsky-upload上传图片 1.说明 先前使用lsky图床的时候&#xff0c;我一直用的是picgo的插件来上传图片。 但最近picgo总是遇到卡上传的问题 https://github.com/Molunerfinn/PicGo/issues/1060 后来在gitee上面搜到了这个项目&…

Django实现接口自动化平台(七)数据库设计

上一章&#xff1a; Django实现接口自动化平台&#xff08;六&#xff09;httprunner&#xff08;2.x&#xff09;基本使用【持续更新中】_做测试的喵酱的博客-CSDN博客 下一章&#xff1a; 一、数据库设计 接口自动化平台&#xff0c;内置引擎&#xff0c;使用的是httprun…

【LeetCode热题100】打卡19天:最大数组和跳跃游戏

文章目录 【LeetCode热题100】打卡第19天&#xff1a;最大数组和&跳跃游戏⛅前言 最大数组和&#x1f512;题目&#x1f511;题解 跳跃游戏&#x1f512;题目&#x1f511;题解 【LeetCode热题100】打卡第19天&#xff1a;最大数组和&跳跃游戏 ⛅前言 大家好&#xff…

A股市场全景分析系列—从每日涨停个股分析热门板块与题材

前言‍‍ 当前市场股票多但资金有限&#xff0c;因此已经无法出现全面上涨的行情。这样一来识别当前的“风口”显得尤为重要&#xff0c;也就是上车热门板块、热门题材、强势个股&#xff01; 因此聚焦分析涨停板个股显得尤为重要&#xff01; 我们统计了近&#xff15;个交易日…

【算法题解】38. 括号的生成

这是一道 中等难度 的题 https://leetcode.cn/problems/generate-parentheses/ 题目 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;["…

DNS隧道穿透

介绍&#xff1a; DNS隧道&#xff0c;是隧道技术中的一种。当我们的HTTP、HTTPS这样的上层协议、正反向端口转发都失败的时候&#xff0c;可以尝试使用DNS隧道。DNS隧道很难防范&#xff0c;因为平时的业务也好&#xff0c;使用也罢&#xff0c;难免会用到DNS协议进行解析&am…

线上问题记录20230610-NGINX代理大文件下载问题

线上问题记录20230610-NGINX代理大文件下载问题 问题描述 我们有一个在线项目&#xff1a;是一个对象文件存储服务&#xff0c;是用来给用户提供文件对象存储的。今天用户在使用的时候发现超过1G的文件无法进行下载。幸好今天是星期六&#xff0c;使用的人并不是特别多&#…