最近,我在網上溜達的時候,看到一個話題讓我心裏一緊——現在除了Boss直聘,其他招聘APP是不是都開始「涼涼」了?這個話題有點直接啊,相信大家都知道這代表什麽意思。
我不點開評論都知道評論區有多精彩。這不,有網友立馬跳出來辟謠:「你們說錯了,Boss直聘也涼了好嗎?」這語氣有點搞笑,但其實很沈重。
但也有表示贊同,「對的,只有boss直聘有活人,其它軟體你過1個月以上都還是未讀」想來,Boss直聘似乎還是不錯的。
也有人開始發表其他說法:「看了一圈58幾乎沒人提及 它才是最涼的」
「我覺得智聯回復率還大些」
「投了兩周了,我的感覺是」
也許,這背後反映的就現在招聘市場的真實情況。但無論如何,對於我們來說,能找到一份滿意的工作始終是目標。我們能做的就是提升自己,他強任他強,清風拂山崗。
下面是今日的大廠演算法題
今日演算法題 ,來自LeetCod e的 第30題:串聯所有單詞的子串,下面是 我的演算法思路及實作,讓我們來看看吧。
# 演算法題目
給定一個字串s和一些長度相同的單詞words。找出s中恰好可以由words中所有單詞串聯形成的子串的起始位置。你可以假設words中的所有單詞長度都相同。
# 演算法思路
哈希對映統計: 首先使用哈希對映(HashMap)統計words陣列中每個單詞出現的次數。
滑動視窗: 由於所有單詞的長度相同,我們可以使用滑動視窗的方式,以單詞的長度為步長在原字串s上滑動,檢查每個可能的視窗。
匹配驗證: 對於每個視窗,使用另一個哈希對映統計視窗中每個單詞的出現次數,然後與words的哈希對映進行比較,看是否完全匹配。
記錄起始位置: 如果一個視窗完全匹配,記錄該視窗的起始位置。
最佳化: 為了減少不必要的檢查,我們只需要在0到wordLength-1的範圍內開始滑動視窗,其中wordLength是陣列words中單詞的長度。
# 程式碼實作
Java實作
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public classSolution{
public List<Integer> findSubstring(String s, String[] words) {
int wordLength = words[0].length();
int allWordsLength = words.length * wordLength;
Map<String, Integer> wordMap = new HashMap<>();
List<Integer> result = new ArrayList<>();
for (String word : words) {
wordMap.put(word, wordMap.getOrDefault(word, 0) + 1);
}
for (int i = 0; i < wordLength; i++) {
for (int j = i; j <= s.length() - allWordsLength; j += wordLength) {
Map<String, Integer> seen = new HashMap<>();
int k = 0;
while (k < words.length) {
String word = s.substring(j + k * wordLength, j + (k + 1) * wordLength);
if (wordMap.containsKey(word)) {
seen.put(word, seen.getOrDefault(word, 0) + 1);
if (seen.get(word) > wordMap.get(word)) break;
} else {
break;
}
k++;
}
if (k == words.length) result.add(j);
}
}
return result;
}
}
JavaScript實作
functionfindSubstring(s, words) {
const wordLength = words[0].length;
const allWordsLength = words.length * wordLength;
const wordMap = newMap();
const result = [];
words.forEach(word => {
wordMap.set(word, (wordMap.get(word) || 0) + 1);
});
for (let i = 0; i < wordLength; i++) {
for (let j = i; j <= s.length - allWordsLength; j += wordLength) {
const seen = newMap();
let k = 0;
while (k < words.length) {
const word = s.substr(j + k * wordLength, wordLength);
if (wordMap.has(word)) {
seen.set(word, (seen.get(word) || 0) + 1);
if (seen.get(word) > wordMap.get(word)) break;
} else {
break;
}
k++;
}
if (k === words.length) result.push(j);
}
}
return result;
}
Go實作
package main
import"fmt"
funcfindSubstring(s string, words []string) []int {
wordLength := len(words[0])
allWordsLength := len(words) * wordLength
wordMap := make(map[string]int)
var result []int
for _, word := range words {
wordMap[word]++
}
for i := 0; i < wordLength; i++ {
for j := i; j <= len(s)-allWordsLength; j += wordLength {
seen := make(map[string]int)
var k int
for k = 0; k < len(words); k++ {
word := s[j+k*wordLength : j+(k+1)*wordLength]
if count, exists := wordMap[word]; exists {
seen[word]++
if seen[word] > count {
break
}
} else {
break
}
}
if k == len(words) {
result = append(result, j)
}
}
}
return result
}
# 演算法解析
這個演算法的關鍵在於如何有效地利用哈希對映來減少不必要的比較。透過維護一個滑動視窗,並在每次叠代中更新這個視窗內單詞的出現次數,我們可以有效地判斷當前視窗是否滿足條件。
此外,透過分步驟處理,即先統計words陣列中單詞的出現次數,然後透過滑動視窗檢查每個子串,這種方法既清晰又易於實作。
# 範例和測試
以s = "barfoothefoobarman", words = ["foo","bar"]為例,我們的函式應該返回[0,9]。這是因為在s中,從索引0開始的子串"barfoo"和從索引9開始的子串"foobar"恰好由words中的所有單詞串聯形成。
# 總結
這道題目展示了在字串處理和演算法設計中哈希對映的強大套用。透過巧妙地利用哈希對映來追蹤和比較子串中單詞的出現次數,我們能夠有效地解決復雜的字串匹配問題。
熱門推薦