LeetCode200
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1
示例 2:
输入:grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] 输出:3
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j]
的值为'0'
或'1'
思路:
dfs
代码:
class Solution {
public:
//bool g[305][305];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
void dfs(vector<vector<char>>& grid,int i,int j)
{
int x,y;
for(int k=0;k<4;k++)
{
x=i+dx[k];
y=j+dy[k];
if(x>=0&&y>=0&&x<grid.size()&&y<grid[0].size()&&grid[x][y]=='1'){
grid[x][y]='0';
dfs(grid,x,y);
}
}
}
int numIslands(vector<vector<char>>& grid) {
//memset(g,0,sizeof(g));
int ans=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]=='1'){
grid[i][j]='0';
dfs(grid,i,j);
ans++;
}
}
}
return ans;
}
};
LeetCode206
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
思路:
三个指针会写起来比较简洁,我们在不断地让一个指针指向它的前一个指针的时候,还需要一个指针向后遍历。
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* p=head;
if(p==NULL||p->next==NULL)return head;
ListNode* q=NULL;
ListNode* t=p->next;
while(p->next)
{
p->next=q;
q=p;
p=t;
t=t->next;
}
p->next=q;
return p;
}
};
LeetCode207
你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi]
,表示如果要学习课程 ai
则 必须 先学习课程 bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
。
示例 1:
输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
提示:
1 <= numCourses <= 105
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i]
中的所有课程对 互不相同
思路:
拓扑排序。
每次找到入度为0的结点,然后就可以把它指向的结点都减去一个入度,然后再找入度为0的结点。
如果当前已经没有入度为0的结点了,但是还有很多点的话,说明就是false。
值得一提的是,我一开始用vector<vector<int> >记录图,RE了。
于是改成了vector<int> a[10001]。居然就可以了。
代码:
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
if(prerequisites.size()==0||numCourses==0||numCourses==1)return 1;
int b[100001];
memset(b,0,sizeof(b));
vector<int> a[100001];
int x,y;
for(int i=0;i<prerequisites.size();i++)
{
x=prerequisites[i][0];
y=prerequisites[i][1];
a[x].push_back(y);
b[y]++;
}
queue<int> q;
for(int i=0;i<numCourses;i++)
{
if(b[i]==0)q.push(i);
}
if(q.size()==0)return 0;
vector<int> ans;
while(q.size())
{
int d=q.front();
q.pop();
ans.push_back(d);
// for(int i=0;i<numCourses;i++)
// {
// if(prerequisites[d][i])b[i]--;
// if(b[i]==0)q.push(i);
// }
for(int i=0;i<a[d].size();i++)
{
b[a[d][i]]--;
if(b[a[d][i]]==0)q.push(a[d][i]);
}
}
if(ans.size()==numCourses)return 1;
else return 0;
}
};
LeetCode208
Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
请你实现 Trie 类:
Trie()
初始化前缀树对象。void insert(String word)
向前缀树中插入字符串word
。boolean search(String word)
如果字符串word
在前缀树中,返回true
(即,在检索之前已经插入);否则,返回false
。boolean startsWith(String prefix)
如果之前已经插入的字符串word
的前缀之一为prefix
,返回true
;否则,返回false
。
示例:
输入 ["Trie", "insert", "search", "search", "startsWith", "insert", "search"] [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]] 输出 [null, null, true, false, true, null, true] 解释 Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // 返回 True trie.search("app"); // 返回 False trie.startsWith("app"); // 返回 True trie.insert("app"); trie.search("app"); // 返回 True
提示:
1 <= word.length, prefix.length <= 2000
word
和prefix
仅由小写英文字母组成insert
、search
和startsWith
调用次数 总计 不超过3 * 104
次
思路:
字典树。
参考【数据结构】字典树TrieTree图文详解_Avalon Demerzel的博客-CSDN博客_字典树
稍微该一改,因为题目里有个比较特殊的地方是,如果有apple但是查询app的话,是false,因为app的p不是一个单词的终止节点。所以加一句判断就好了。
代码:
class Trie {
private:
int n;
int priv[1000050][26];
int id;
int cnt[1000050];
public:
Trie() {
memset(priv,0,sizeof(priv));
memset(cnt,0,sizeof(cnt));
id=0;
n=2001;
}
void insert(string word) {
int p=0;
for(int i=0;i<word.length();i++)
{
int x=word[i]-'a';
if(priv[p][x]==0)priv[p][x]=++id;
p=priv[p][x];
}
cnt[p]++;
}
bool search(string word) {
int p=0;
for(int i=0;i<word.length();i++)
{
int x=word[i]-'a';
if(priv[p][x]==0)return 0;
p=priv[p][x];
}
if(cnt[p]==0)return 0;
return 1;
}
bool startsWith(string prefix) {
int p=0;
for(int i=0;i<prefix.length();i++)
{
int x=prefix[i]-'a';
if(priv[p][x]==0)return 0;
p=priv[p][x];
}
return 1;
}
};
/**
* 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);
*/