leetcode刷题笔记
21 面试题13. 机器人的运动范围 难度:中等
奇奇怪怪bug:先检验x和y是否越界,再检验visited[x][y]是否访问。否则会出现诡异的越界错误。
注意vector二维数组的定义和初始化写法。
dfs思想,多加练习。
class Solution {
public:
int movingCount(int m, int n, int k) {
vector<vector<int> > visited (m, vector<int> (n, 0));
return dfs(0, 0, m, n, k, visited);
}
int dfs(int x, int y, int m, int n, int k, vector<vector<int> >& visited){
if(x>=m || y>=n ||visited[x][y] == 1 || (x/10 + x%10 + y/10 + y%10) > k){
return 0;
}
visited[x][y] = 1;
return 1 + dfs(x+1, y, m, n, k, visited) + dfs(x, y+1, m, n, k, visited);
}
};
执行用时 :0 ms, 在所有 C++ 提交中击败了100.00% 的用户
内存消耗 :6.9 MB, 在所有 C++ 提交中击败了100.00%的用户
22 151. 翻转字符串里的单词 难度:中等
我的方法:vector存储string,先后面加个空格就不用最后特殊判断了,用bool控制忽略连续的空格。
因为库用的比较多,应该很费时。
class Solution {
public:
string reverseWords(string s) {
s+=' ';
vector<string> vec;
int t=0;
bool space=false;
string temp;
while(t<s.size()){
if(s[t]!=' '){
temp+=s[t];
space=true;
}
else if(s[t]==' '){
if(space==true){
vec.push_back(temp);
temp.clear();
space=false;
}
}
t++;
}
string s1;
for(int i=vec.size()-1;i>=0;i--){
if(i!=0){
s1+=vec[i];
s1+=' ';
}
else{
s1+=vec[i];
}
}
return s1;
}
};
执行用时 :24 ms, 在所有 C++ 提交中击败了18.68% 的用户
内存消耗 :8.7 MB, 在所有 C++ 提交中击败了100.00%的用户
23 445. 两数相加 II 难度:中等
用的栈存储两个链表,头插法建立新链表。
很多其他思路可以看看题解区,反转链表,转字符串,也有原地操作的,等等。
坑:判断循环结束时,两栈空但有进位,不能结束循环。
定义节点的时候别忘了用构造函数初始化一下。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1, s2;
while(l1!=NULL){
s1.push(l1->val);
l1=l1->next;
}
while(l2!=NULL){
s2.push(l2->val);
l2=l2->next;
}
int carry=0,sum=0;
ListNode* head = new ListNode(0);
while(!s1.empty() || !s2.empty() || carry!=0){
int a = s1.empty()?0:s1.top();
int b = s2.empty()?0:s2.top();
sum = a + b + carry;
ListNode* l = new ListNode(sum%10);
carry=sum/10;
l->next = head->next;
head->next = l;
if(!s1.empty()) s1.pop();
if(!s2.empty()) s2.pop();
}
return head->next;
}
};
执行用时 :64 ms, 在所有 C++ 提交中击败了12.70% 的用户
内存消耗 :73.8 MB, 在所有 C++ 提交中击败了11.11%的用户
24 11. 盛最多水的容器 难度:中等
一看题目就知道有好算法,然后怒模拟:
class Solution {
public:
int maxArea(vector<int>& height) {
int m_a = 0;
int l = height.size();
for(int i=0;i<l-1;i++){
for(int j=i+1;j<l;j++){
int area = (j-i)*min(height[i], height[j]);
m_a = area>m_a?area:m_a;
}
}
return m_a;
}
};
果然超出时间限制了!^ ^
根据题解,使用双指针:
class Solution {
public:
int maxArea(vector<int>& height) {
int max = 0;
int head = 0, rear = height.size()-1;
while(head<rear){
int area = (rear - head) * min(height[head], height[rear]);
if(area>max) max=area;
if(height[head]>height[rear]) rear--;
else head++;
}
return max;
}
};
执行用时 :16 ms, 在所有 C++ 提交中击败了85.84% 的用户
内存消耗 :7.5 MB, 在所有 C++ 提交中击败了100.00%的用户
做到现在,99%的题依然感觉毫无思路,只能模拟。算法能力到底是见得太多–>看什么都熟悉–>立刻就知道往哪方面想,还是能凭空想出来好的解法?我暂且蒙在鼓里
25 206. 反转链表 难度:中等
反转链表,双指针。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *p = head, *q = NULL;
while(p!=NULL){
ListNode* temp = p->next;
p->next = q;
q = p;
p = temp;
}
return q;
}
};
执行用时 :12 ms, 在所有 C++ 提交中击败了31.29% 的用户
内存消耗 :8.4 MB, 在所有 C++ 提交中击败了100.00%的用户
26 200. 岛屿数量 难度:中等
我的代码很不优雅,dfs不够熟练。而且我的函数参数太多了注意一下网友的简洁解法。
有一个小坑:输入是空[]时要单独处理。
class Solution {
public:
void search(int i, int j, vector<vector<char>>& grid){
grid[i][j]='0';
if(i<(grid.size()-1) && grid[i+1][j]=='1') search(i+1,j,grid);
if(j<(grid[0].size()-1) && grid[i][j+1]=='1') search(i,j+1,grid);
if(i>0 && grid[i-1][j]=='1') search(i-1,j,grid);
if(j>0 && grid[i][j-1]=='1') search(i,j-1,grid);
}
int numIslands(vector<vector<char>>& grid) {
if(grid.empty()) return 0;
int num = 0;
for(int i=0;i<grid.size();i++){
for(int j=0;j<grid[0].size();j++){
if(grid[i][j] == '1'){
num++;
search(i,j,grid);
} /* 是陆地 */
}
}
return num;
}
};
执行用时 :12 ms, 在所有 C++ 提交中击败了86.76% 的用户
内存消耗 :8.3 MB, 在所有 C++ 提交中击败了100.00%的用户
27 7. 整数反转 难度:简单
这是道简单题,记录一下INT_MAX和INT_MIN的用法。
class Solution {
public:
int reverse(int x) {
int y=0;
while(x){
if(y>INT_MAX/10 || y<INT_MIN/10){
return 0;
}
int t = x%10;
y = y*10 + t;
x /= 10;
}
return y;
}
};
执行用时 :4 ms, 在所有 C++ 提交中击败了67.75% 的用户
内存消耗 :6.1 MB, 在所有 C++ 提交中击败了100.00%的用户
28 13. 罗马数字转整数 难度:简单
也是简单题,复习map的用法。map赋值不用函数。
class Solution {
public:
int romanToInt(string s) {
unordered_map<char, int> mp;
mp['I'] = 1;
mp['V'] = 5;
mp['X'] = 10;
mp['L'] = 50;
mp['C'] = 100;
mp['D'] = 500;
mp['M'] = 1000;
int sum = 0;
for(int i=0;i<s.size();i++){
if(mp[s[i]] < mp[s[i+1]]){
sum -= mp[s[i]];
}
else {
sum += mp[s[i]];
}
}
return sum;
}
};
执行用时 :28 ms, 在所有 C++ 提交中击败了42.34% 的用户
内存消耗 :8.9 MB, 在所有 C++ 提交中击败了55.71%的用户
29 13. 罗马数字转整数 难度:简单
跟本篇中的 第23 是同一题,这次没用栈,用的直接操作链表,头插法。两种对比着看。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(0);
ListNode* r = head;
int index = 0;
while(l1!=NULL || l2!=NULL || index!=0){
int sum = 0;
if(l1){
sum+=l1->val;
}
if(l2){
sum+=l2->val;
}
sum+=index;
ListNode* temp = new ListNode(sum%10);
index = sum/10;
head->next = temp;
head = temp;
if(l1){
l1 = l1->next;
}
if(l2){
l2 = l2->next;
}
}
return r->next;
}
};
执行用时 :32 ms, 在所有 C++ 提交中击败了50.51% 的用户
内存消耗 :9.3 MB, 在所有 C++ 提交中击败了100.00%的用户
30 3. 无重复字符的最长子串 难度:中等
滑动窗口经典题,本想用map记录位置,后面还是改成用set只记录值,然后设一个left指针记录起始位置。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> st;
int maxlen = 0;
int left = 0, i;
for(i=0;i<s.size();i++){
if(st.find(s[i]) == st.end()){
st.insert(s[i]);
}
else{
maxlen = max(maxlen, i - left);
while(s[left] != s[i]){
st.erase(s[left]);
left++;
}
left++;
}
}
maxlen = max(maxlen, i-left);
return maxlen;
}
};
执行用时 :40 ms, 在所有 C++ 提交中击败了36.23% 的用户
内存消耗 :9.2 MB, 在所有 C++ 提交中击败了78.89%的用户