贪心算法:
回溯算法:
动态规划:
分治算法:
线段树:
滑动窗口:
队列:
堆栈:
链表:
字典树 :
676. 实现一个魔法字典 211. 添加与搜索单词 - 数据结构设计
class WordDictionary
{
public:
struct Node
{
Node* son[26];
bool is_end;
Node() {
is_end = false;
for (int i = 0; i < 26 ; i++)
{
son[i] = nullptr;
}
}
} *root;
WordDictionary() {
root = new Node();
};
void addWord(string word) {
auto p = root;
for (auto c : word)
{
int u = c - 'a';
if (!p->son[u]) {
p->son[u] = new Node();
}
p = p->son[u];
}
p->is_end = true;
}
bool find_word(Node* croot, string& word, int si) {
if (si == word.size()) return croot->is_end;
if (word[si] == '.') {
// 从root头开始遍历,一一匹配
for (int i = 0; i < 26; i++)
{
if (croot->son[i] && find_word(croot->son[i], word, si + 1)) {
return true;
}
}
} else {
int u = word[si] - 'a';
if (croot->son[u]) {
return find_word(croot->son[u], word, si + 1);
} else {
return false;
}
}
return false;
}
bool search(string word) {
return find_word(root, word, 0);
}
};
class Trie {
private:
bool isEnd;
vector<Trie*> children;
Trie* searchWord(string word) {
Trie* node = this;
for(char w : word) {
w -= 'a';
if (node->children[w] == nullptr) {
return nullptr;
}
node = node->children[w];
}
return node;
}
public:
/** Initialize your data structure here. */
Trie() : children(26), isEnd(false) {}
/** Inserts a word into the trie. */
void insert(string word) {
Trie* node = this;
for(char w : word) {
w -= 'a';
if (node->children[w] == nullptr) {
node->children[w] = new Trie();
}
node = node->children[w];
}
node->isEnd = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
Trie* node = this->searchWord(word);
return node != nullptr && node->isEnd;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
return this->searchWord(prefix) != nullptr;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
map + sort + sub
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
trie = {}
WORD_KEY = '$'
# 更新node
for word in words :
node = trie
for letter in word :
node = node.setdefault(letter, {})
node[WORD_KEY] = word
rowNum = len(board)
colNum = len(board[0])
matchedWord = []
def trackWord(row, col, parent) :
letter = board[row][col]
currNode = parent[letter]
word_match = currNode.pop(WORD_KEY, False)
if word_match :
matchedWord.append(word_match)
board[row][col] = '#'
for (dirRow, dirCol) in [(-1, 0), (0, 1), (1, 0), (0, -1)] :
newRow = row + dirRow
newCol = col + dirCol
if newRow < 0 or newRow >= rowNum or newCol < 0 or newCol >= colNum:
continue
if not board[newRow][newCol] in currNode:
continue
trackWord(newRow, newCol, currNode)
board[row][col] = letter
if not currNode:
parent.pop(letter)
for row in range(rowNum) :
for col in range(colNum) :
if board[row][col] in trie :
trackWord(row, col, trie)
return matchedWord
并查集:
128. 最长连续序列 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
时间复杂度为 O(n)
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> myset;
// 使用set
for(const int& s: nums) {
myset.insert(s);
}
int maxlen = 0;
for (int i = 0; i < nums.size(); ++i) {
// 从头开始
if (!myset.count(nums[i] - 1)) {
int len = 1;
int j = i;
// 遍历后续+1节点
while(myset.count(nums[j] + 1)) {
len += 1;
j++;
}
maxlen = max(maxlen, len);
}
}
return maxlen;
}
};
private class UnionFind {
private int[] parent;
public UnionFind(int n) {
this.parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
//找根
public int root(int x) {
while (x != parent[x]) {
//parent[x]往下遍历
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
//根是否同一个
public boolean isConnected(int x, int y) {
return root(x) == root(y);
}
public void union(int p, int q) {
if (isConnected(p, q)) {
return;
}
//合并俩节点的根
parent[root(p)] = root(q);
}
}
public class Solution {
private int N;
public static final int[][] DIRECTIONS = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int swimInWater(int[][] grid) {
this.N = grid.length;
int len = N * N;
// 下标:方格的高度,值:对应在方格中的坐标
int[] index = new int[len];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
index[grid[i][j]] = getIndex(i, j);
}
}
UnionFind unionFind = new UnionFind(len);
for (int i = 0; i < len; i++) {
int x = index[i] / N;
int y = index[i] % N;
for (int[] direction : DIRECTIONS) {
int newX = x + direction[0];
int newY = y + direction[1];
if (inArea(newX, newY) && grid[newX][newY] <= i) {
unionFind.union(index[i], getIndex(newX, newY));
}
if (unionFind.isConnected(0, len - 1)) {
return i;
}
}
}
return -1;
}
private int getIndex(int x, int y) {
return x * N + y;
}
private boolean inArea(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < N;
}
private class UnionFind {
private int[] parent;
public UnionFind(int n) {
this.parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public int root(int x) {
while (x != parent[x]) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
public boolean isConnected(int x, int y) {
return root(x) == root(y);
}
public void union(int p, int q) {
if (isConnected(p, q)) {
return;
}
parent[root(p)] = root(q);
}
}
}
class Test {
constructor(node) {
for() {
this.parent[i] = i;
}
}
toUnion(x, y) {
if (isConnected(x, y)) return
this.parent[getRoot(x)] = getRoot(y)
}
isConnected(x, y) {
return getRoot(x) == getRoot(y)
}
getRoot(x) {
while(x != this.parent[x]) {
this.parent[x] = this.parent[this.parent[x]];
x = this.parent[x];
}
return x;
}
}
const t = new Test("aa")
right = N*N - 1
while(left < right) {
mid = (left + right) >> 2
visited = [][]
if (grid[][] <= mid && dfs(grid, 0, 0, visited, mid)) {
right = mid
} else {
left = mid
}
}
return left
dfs() {
visited[][] = true
for(dir in {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}) {
if (inArea() && !visited[grid[newx][newy]] && grid[newx][newy] <= threshold) {
if (== N - 1) return true
return dfs(grid, newx, newy, visited, threshold)
}
}
return false
}
bfs() {
queue = [][]
queue.offer({0, 0})
boolean[][] visited = new boolean[N][N];
visited[0][0] = true
while(!queue.empty()) {
node = queue.poll
x = node[0], y = node[1]
for(dir in {}) {
newx = x + dir, newy = y + dir
if (inarea() && !visited && bfs()) {
if (== N - 1) return true
queue.offer([newx, newy])
visited[][] = true
}
}
}
return false
}
Queue<int> miniHeap = new PriorityQueue<>(Comparator.comparingInt(o->grid[o[0]][o[1]]))
int distto = new Int[n][n]
for(row in disto) {
Arrays.fill(row, n*n)
}
for() {
pqueue.push({0, 0})
while(!pqueue.empty) {
node = pqueue.poll()
x = node[0]
y = node[1]
for (dir in dirs) {
newx = dir[0] + x;
newy = dir[1] + y;
if (inarea(newx, newy) && !visited && max(distto(), gird()) < distto[newx][newy]) {
distto[newx][newy] = max(distto(), gird())
}
visited[][] = true
pqueue.offer({newx, newy})
}
}
return -1
}