242.有效的字母异位词
题意:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true
示例 2: 输入: s = “rat”, t = “car” 输出: false
说明: 你可以假设字符串只包含小写字母。
思路:这道题可以用哈希表来解决,只需要判断s 和 t 是否有不相同的字母,不用考虑字母出现的顺序,符合哈希表能够快速找出一个元素的特点。首先掌握哈希表的构造,在c++中可以通过定义数组来实现(哈希表的键对应数组的索引),js中可以结合Array或者map来构造。
解法:
- 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;
}
};
- javascript
// 1. Array方法
var isAnagram = function(s, t) {
if(s.length !== t.length) return false; // 如果数组长度不相同,一定为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;
};
// 2. map方法
var isAnagram = function(s, t) {
if(s.length !== t.length) return false;
let char_count = new Map();
for(let item of s) {
char_count.set(item, (char_count.get(item) || 0) + 1) ;
}
for(let item of t) {
if(!char_count.get(item)) return false; // 如果map中对应的字符的值为0,说明s中没有出现,直接返回false
char_count.set(item, char_count.get(item)-1);
}
return true;
};
笔记:(补充一些js的基础知识)
- Array.fill() 方法:会改变原数组
// 创建一个长度为5的数组,并填充为0
let arr = new Array(5).fill(0);
console.log(arr); // [0, 0, 0, 0, 0]
// 创建一个长度为3的数组,并填充为'hello'
let newArr = new Array(3).fill('hello');
console.log(newArr); // ['hello', 'hello', 'hello']
// 从索引1开始填充到索引3(不包括)
let arr2 = [1, 2, 3, 4, 5];
arr2.fill('a', 1, 3);
console.log(arr2); // [1, 'a', 'a', 4, 5]
- for… in和for…of的区别:
for...of
和 for...in
是 JavaScript 中用于循环的两种不同语法,它们各自有不同的用途和行为。
- for…of 循环:
- 用于遍历可迭代对象(iterable),比如数组、字符串、Map、Set 等。
- 在每次迭代中,会将可迭代对象中的值赋给循环变量,而不是索引。
- 不支持普通对象的遍历,因为普通对象不是可迭代对象。
示例用法:
let arr = [1, 2, 3];
for (let value of arr) {
console.log(value); // 1, 2, 3
}
let str = "hello";
for (let char of str) {
console.log(char); // 'h', 'e', 'l', 'l', 'o'
}
- for…in 循环:
- 用于遍历对象的可枚举属性,包括自身和继承的可枚举属性。
- 在每次迭代中,会将对象的属性名赋给循环变量,而不是属性值。
- 一般不推荐用于遍历数组,因为它会遍历数组的所有可枚举属性,包括数组的原型链上的属性。
示例用法:
let obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
console.log(key); // 'a', 'b', 'c'
console.log(obj[key]); // 1, 2, 3
}
let arr = [1, 2, 3];
for (let index in arr) {
console.log(index); // '0', '1', '2'
console.log(arr[index]); // 1, 2, 3
}
总之,for...of
适用于遍历可迭代对象的值,而 for...in
适用于遍历对象的属性名。
- js的 map 和 set 的区别:
在 JavaScript 中,Map
和 Set
都是用来存储数据集合的数据结构,它们有一些区别:
- Map:
Map
是一种键值对的集合,其中每个键都唯一,并且可以存储任意类型的值。- 键可以是任意数据类型,包括基本类型和对象引用。
- 可以通过
set(key, value)
方法设置键值对,通过get(key)
方法获取值,通过delete(key)
方法删除键值对,以及通过has(key)
方法检查键是否存在。 - 可以迭代其中的键值对,支持
for...of
循环和forEach
方法。 Map
中的键值对是有序的,插入顺序决定了迭代顺序。
示例用法:
let map = new Map();
map.set('key1', 'value1');
map.set('key2', 'value2');
console.log(map.get('key1')); // 'value1'
console.log(map.has('key2')); // true
map.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
- Set:
Set
是一种值的集合,其中每个值都是唯一的,不允许重复。- 可以存储任意类型的值,但不允许重复的值存在。
- 可以通过
add(value)
方法添加值,通过delete(value)
方法删除值,以及通过has(value)
方法检查值是否存在。 - 可以迭代其中的值,支持
for...of
循环和forEach
方法。 Set
中的值是有序的,但插入顺序不会影响迭代顺序。
示例用法:
let set = new Set();
set.add('value1');
set.add('value2');
console.log(set.has('value1')); // true
set.forEach(value => {
console.log(value);
});
总的来说,Map
适用于需要键值对存储的情况,而 Set
适用于需要存储唯一值的情况。