哈希表
127. 单词接龙
题目
字典
wordList
中从单词beginWord
到endWord
的 转换序列 是一个按下述规格形成的序列beginWord -> s(1) -> s(2) -> ... -> s(k)
:
每一对相邻的单词只差一个字母。
对于
1 <= i <= k
时,每个s(i)
都在wordList
中。注意,beginWord
不需要在wordList
中。
s(k) == endWord
给你两个单词
beginWord
和endWord
和一个字典wordList
,返回 从beginWord
到endWord
的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回0
。示例 1:
输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] 输出: 5 解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
示例 2:
输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"] 输出: 0 解释: endWord "cog" 不在字典中,所以无法进行转换。提示:
1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord
、endWord
和wordList[i]
由小写英文字母组成
beginWord != endWord
wordList
中的所有字符串 互不相同
题解
javascript
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {number}
*/
var ladderLength = function (beginWord, endWord, wordList) {
if (beginWord === endWord) return 1
let newSetWordList = new Set(wordList);
let que = [];
que.push([beginWord, 1])//第一次默认值,beginWord,默认长度1
while (que.length) {
for (var i = 0; i < que.length; i++) {
let [newBeginWord, level] = que.shift()
if (newBeginWord === endWord) {//相等时,返回长度
return level
}
for (var w = 0; w < newBeginWord.length; w++) {//循环需要转换的字符串
for (var j = 97; j <= 122; j++) {// 26个小写字母(ascii码 http://ascii.911cha.com/)
let newStr = newBeginWord.slice(0, w) + String.fromCharCode(j) + newBeginWord.slice(w + 1)//hit -》 xit hxt hix x代表26个小写字母
if (newSetWordList.has(newStr)) {
que.push([newStr, level + 1]) //把转换后的newStr放到数组中,长度+1
newSetWordList.delete(newStr)//匹配到删除
}
}
}
}
}
return 0;
};
140. 单词拆分 II
题目
给定一个字符串
s
和一个字符串字典wordDict
,在字符串s
中增加空格来构建一个句子,使得句子中所有的单词都在词典中。以任意顺序 返回所有这些可能的句子。
注意: 词典中的同一个单词可能在分段中被重复使用多次。示例 1:
输入: s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"] 输出: ["cats and dog","cat sand dog"]
示例 2:
输入: s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"] 输出: ["pine apple pen apple","pineapple pen apple","pine applepen apple"] 解释: 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"] 输出: []提示:
1 <= s.length <= 20
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 10
s
和wordDict[i]
仅有小写英文字母组成
wordDict
中所有字符串都 不同
题解
javascript
/**
* @param {string} s
* @param {string[]} wordDict
* @return {string[]}
*/
var wordBreak = function (s, wordDict) {
const sIndex = s.length;
const newWordDict = new Set(wordDict);//set 数据结构有has方法
let hash = new Map();//存储循环过的从start截取i对应的数据
function drt(start) {
if (hash.has(start)) {//hash里有start,直接取对应的数据
return hash.get(start);
}
if (start > sIndex - 1) {//start 最大值就是字符串最后一个索引 sIndex - 1
return [[]];
}
let res = [];
for (var i = start + 1; i <= sIndex; i++) {
let str = s.slice(start, i);
if (newWordDict.has(str)) {
const items = drt(i);//循环把剩余字符串在newWordDict进行匹配,返回数组res [[string],]
for (let item of items) {
res.push([str].concat(item));
}
}
hash.set(start, res);//存储从start开始截取,对应的res数据
}
return res;
}
return drt(0).map((item) => item.join(" "));// [[string,string],[string,string]] 变成 ["string string","string string"]
};
383. 赎金信
题目
给你两个字符串:
ransomNote
和magazine
,判断ransomNote
能不能由magazine
里面的字符构成。如果可以,返回
true
;否则返回false
。
magazine
中的每个字符只能在ransomNote
中使用一次。示例 1:
输入: ransomNote = "a", magazine = "b" 输出: false
示例 2:
输入: ransomNote = "aa", magazine = "ab" 输出: false
示例 3:
输入: ransomNote = "aa", magazine = "aab" 输出: true提示:
1 <= ransomNote.length, magazine.length <= 10(5)
ransomNote
和magazine
由小写英文字母组成
题解
javascript
/**
* @param {string} ransomNote
* @param {string} magazine
* @return {boolean}
*/
var canConstruct = function (ransomNote, magazine) {
let wordMap = {}; // magazine字符每个字母出现次数
let i = 0,
j = 0;
// 统计 magazine字符26个字母出现次数
while (i < magazine.length) {
const key = magazine[i];
const wordNum = wordMap[key];
wordMap[key] = wordNum ? wordNum + 1 : 1;
i++;
}
// 循环ransomNote字符消耗map里对应字母次数
while (j < ransomNote.length) {
const ranKey = ransomNote[j];
if (wordMap[ranKey] > 0) {
wordMap[ranKey] -= 1;
} else {
return false;
}
j++;
}
return true;
};
2744. 最大字符串配对数目
题目
给你一个下标从 0 开始的数组
words
,数组中包含 互不相同 的字符串。如果字符串
words[i]
与字符串words[j]
满足以下条件,我们称它们可以匹配:
字符串
words[i]
等于words[j]
的反转字符串。
0 <= i < j < words.length
请你返回数组
words
中的 最大 匹配数目。注意,每个字符串最多匹配一次。
示例 1:
输入: words = ["cd","ac","dc","ca","zz"] 输出: 2 解释: 在此示例中,我们可以通过以下方式匹配 2 对字符串: - 我们将第 0 个字符串与第 2 个字符串匹配,因为 word[0] 的反转字符串是 "dc" 并且等于 words[2]。 - 我们将第 1 个字符串与第 3 个字符串匹配,因为 word[1] 的反转字符串是 "ca" 并且等于 words[3]。 可以证明最多匹配数目是 2 。
示例 2:
输入: words = ["ab","ba","cc"] 输出: 1 解释: 在此示例中,我们可以通过以下方式匹配 1 对字符串: - 我们将第 0 个字符串与第 1 个字符串匹配,因为 words[1] 的反转字符串 "ab" 与 words[0] 相等。 可以证明最多匹配数目是 1 。
示例 3:
输入: words = ["aa","ab"] 输出: 0 解释: 这个例子中,无法匹配任何字符串。提示:
1 <= words.length <= 50
words[i].length == 2
words
包含的字符串互不相同。
words[i]
只包含小写英文字母。
题解
javascript
/**
* @param {string[]} words
* @return {number}
*/
var maximumNumberOfStringPairs = function (words) {
const indexMap = {};
let sum = 0;
for (let i = 0; i < words.length; i++) {
if (indexMap[words[i]]) {
sum++;
} else {
const [a, b] = words[i];
indexMap[b + a] = true;
}
}
return sum;
};
3158. 求出出现两次数字的 XOR 值
题目
给你一个数组
nums
,数组中的数字 要么 出现一次,要么 出现两次。请你返回数组中所有出现两次数字的按位
XOR
值,如果没有数字出现过两次,返回 0 。示例 1:
输入: nums = [1,2,1,3]
输出: 1
解释:
nums
中唯一出现过两次的数字是 1 。
示例 2:
输入: nums = [1,2,3]
输出: 0
解释:
nums
中没有数字出现两次。
示例 3:
输入: nums = [1,2,2,1]
输出: 3
解释:数字 1 和 2 出现过两次。
1 XOR 2 == 3
。提示:
1 <= nums.length <= 50
1 <= nums[i] <= 50
nums
中每个数字要么出现过一次,要么出现过两次。
题解
javascript
/**
* @param {number[]} nums
* @return {number}
*/
var duplicateNumbersXOR = function (nums) {
const aryMap = {};
for (let i = 0; i < nums.length; i++) {
let item = nums[i];
if (aryMap[item]) {
aryMap[item] += 1;
} else {
aryMap[item] = 1;
}
}
return Object.entries(aryMap).reduce((prev, cur) => {
const [key, value] = cur;
return value > 1 ? prev ^ key : prev;
}, 0);
};