国庆七天乐LeetCode算法14天集训营题解(1~7天)
Posted 沉迷单车的追风少年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了国庆七天乐LeetCode算法14天集训营题解(1~7天)相关的知识,希望对你有一定的参考价值。
国庆正好空闲,想着好久没有刷题了(太懒),应该push自己一点,那就看看简单的算法集训营吧~
在数学和计算机科学之中,算法是一个被定义好的、计算机可施行之指示的有限步骤或次序,常用于计算、数据处理和自动推理。作为一个有效方法,算法被用于计算函数,它包含了一系列定义清晰的指令,并可于有限的时间及空间内清楚的表述出来。
目录
第一天:二分查找
LeetCode704.二分查找
直接暴力也可以过:
class Solution {
public:
int search(vector<int>& nums, int target) {
int ans = -1;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == target) {
return i;
}
}
return ans;
}
};
真正的二分:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
};
LeetCode278.第一个错误的版本
暴力直接爆掉,拙劣
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
// int ans = -1;
for (int i = 1; i <= n; i++) {
if (isBadVersion(i)) {
return i;
}
}
return -1;
}
};
还是老老实实二分法:
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
long long int left = 1;
long long int right = n;
while (left < right) {
long long int mid = (left + right) /2;
if (isBadVersion(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return right;
}
};
LeetCode35.搜索插入位置
暴力瞎鸡巴搞:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int pos = nums.size();
for(int i = 0; i < nums.size(); i++){
if(nums[i] >= target){
return i;
}
}
return pos;
}
};
有B格的二分法,居然运行时间更慢,我佛了。。。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target){
left = mid + 1;
} else {
return mid;
}
}
return right + 1;
}
};
第二天:双指针
LeetCode977.有序数组的平方
瞎鸡巴写,也能过……
class Solution {
public:
vector<int> sortedSquares(vector<int>& A) {
for(int i=0;i<A.size();i++){
A[i]*=A[i];
}
sort(A.begin(),A.end());
return A;
}
};
卧槽,原来我一年前做过啊。。
哥的青春被狗吃了
双指针就是利用递增数组的性质,依次比较加入到数组当中,没啥意思,不写了,就是任性
LeetCode.189旋转数组
我记得华为机试经常出现这一题,简单一点的思路就是经过三次旋转就能搞定
class Solution {
public:
void rotate(vector<int>& nums, int k) {
k %= nums.size();
reverse(nums.begin(), nums.end());
reverse(nums.begin() + k, nums.end());
reverse(nums.begin(), nums.begin() + k);
}
};
好像也是剑指offer里面的原题,好像这样交换的时间复杂度最低了,O(n),那就先过吧,搞什么双指针,再见。
第三天:双指针
LeetCode283.移动零
忘记是不是剑指offer上面的了……这样做的时间复杂度也是O(N)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
// 双指针,一个指针用于遍历数组,一个指针用于处理非0
int j = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != 0) {
nums[j++] = nums[i];
}
}
while(j < nums.size()) {
nums[j++] = 0;
}
}
};
LeetCode167.两数之和II-输入有序数组
为啥都是我做过的呀。。。。没意思
最好的方法就是定义一个双指针去寻找,这样的时间复杂度最低了。
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> ans;
int left = 0;
int right = numbers.size() - 1;
while (left < right) {
if (numbers[left] + numbers[right] == target) {
ans.push_back(++left);
ans.push_back(++right);
return ans;
} else if (numbers[left] + numbers[right] < target) {
left++;
} else {
right--;
}
}
return ans;
}
};
第四天:双指针
LeetCode344.反转字符串
之前写过一行代码就解LeetCode,可以没啥人看,可恶啊……都不喜欢玩。。。
class Solution {
public:
void reverseString(vector<char>& s) {
reverse(s.begin(),s.end());
}
};
双指针的解法就不搞了,下一个
LeetCode557.反转字符串中的单词III
看代码,easy,很符合那种水一点的笔试面试,就是想一分钟内A掉还是蛮考验人的。。。
class Solution {
public:
string reverseWords(string s) {
// 双指针,j用于找后一个空格,i用于前一个空格
int i = 0;
int j = 0;
while (j < s.size()) {
while (s[j] != ' ' && j < s.size())
j++;
reverse(s.begin() + i, s.begin() + j);
i = ++j;
}
return s;
}
};
第五天:双指针
LeetCode876.链表的中间结点
最经典的快慢指针题目,过瘾啊!
/**
* 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* middleNode(ListNode* head) {
auto fast = head;
auto slow = head;
while (fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
};
还是我刚开始刷题时候学会的,哎,那时候真的学了好多东西呀
LeetCode19.删除链表的倒数第N个结点
卧槽,这也是我刚学数据结构的时候刷的题啊!
经典快慢指针,快指针先走n步而已。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head == nullptr || head->next == nullptr)
return nullptr;
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* fast, *slow;
fast = slow = head;
while (n) {
fast = fast->next;
n--;
}
// 当n等于链表长度的时候,这种情况应当特殊处理!
if(!fast)
return head->next;
while(fast->next!=nullptr&&fast!=nullptr){
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy->next;
}
};
第六天:滑动窗口
LeetCode3.无重复字符的最长子串
有意思的题目终于来了……
很经典的滑动窗口,因为unordered_set中底层是哈希表,count平均时间复杂度是O(1),而find的时间复杂度为O(logN);但是set底层是红黑树,count时间复杂度就是O(logN)了。所以用哈希表代替数组,表示滑动窗口。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.empty()) {
return 0;
}
int left = 0;
int ans = 0;
unordered_set<char> hash;
for (int right = 0; right < s.size(); right++) {
// 如果窗口右侧字符的出现过,从左边缩小窗口
while (hash.count(s[right])) {
hash.erase(s[left]);
left ++;
}
// 继续从右侧扩大窗口
hash.insert(s[right]);
// 时刻维护最大长度
ans = max(ans, right - left + 1);
}
return ans;
}
};
LeetCode567.字符串的排列
做到目前为止终于碰到我没有做过的题目了,哈哈哈哈搞起来冲
这道题的排列并没有强调顺序,因此我们对于顺序不再关注。
可是怎样做到不关注顺序呢?一种方法是排序后比较。这样的时间复杂度比较高。
另一种好的方法是维护一个哈希表,这个哈希表中存放着每个字符出现的次数,每一次滑动窗口的时候记得改变。
class Solution {
public:
bool checkInclusion(string s1, string s2) {
if (s2.empty() || (s1.size() > s2.size())) {
return false;
}
// 记录字符串中出现的次数
vector<int> h1(26, 0);
vector<int> h2(26, 0);
for (int i = 0; i < s1.size(); i++) {
h1[s1[i] - 'a']++;
h2[s2[i] - 'a']++;
}
for (int i = s1.size(); i < s2.size(); i++) {
if (h1 == h2) {
return true;
}
// 匹配不成功窗口向右滑动
h2[s2[i - s1.size()] - 'a']--;
h2[s2[i] - 'a']++;
}
return h1 == h2;
}
};
第七天:广度优先搜索/深度优先搜索
LeetCode733.图像渲染
这道题和200题经典岛屿是一模一样的,经典,后面可以考虑写一个专辑来介绍
class Solution {
public:
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
if (image.empty() || image.size() == 0 || image[0].size() == 0) {
return image;
}
if (image[sr][sc] == newColor) {
return image;
}
dfs(image, sr, sc, newColor, image[sr][sc]);
return image;
}
void dfs(vector<vector<int>>& image, int i, int j, int newColor, int oldColor) {
// 先写终止条件
if (i < 0 || j < 0 || i >= image.size() || j >= image[0].size()
|| image[i][j] != oldColor) {
return;
}
// 再标记为已经搜索过
image[i][j] = newColor;
// 继续下一次搜索
dfs(image, i - 1, j, newColor, oldColor);
dfs(image, i + 1, j, newColor, oldColor);
dfs(image, i, j + 1, newColor, oldColor);
dfs(image, i, j - 1, newColor, oldColor);
}
};
LeetCode695.岛屿的最大面积
好家伙,看上去像是DFS的模板题,冲~
class Solution {
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
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) {
ans = max(dfs(grid, i, j), ans);
}
}
}
return ans;
}
int dfs(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || j < 0|| i >= grid.size() || j >= grid[0].size()
|| grid[i][j] == 0) {
return 0;
}
grid[i][j] = 0;
int count = 1;
count += dfs(grid, i - 1, j);
count += dfs(grid, i + 1, j);
count += dfs(grid, i, j - 1);
count += dfs(grid, i, j + 1);
return count;
}
};
国庆七天的题就写完了,爽不爽?开始没啥意思,因为大多数都是我写过的题目,后面的题目学到了不少东西。
很久很久没有写LeetCode系列了,看到群里有的人一道题就发一篇blog,解析也就几十个字。照他这样,我一天一篇能写到明年哈哈哈……
以上是关于国庆七天乐LeetCode算法14天集训营题解(1~7天)的主要内容,如果未能解决你的问题,请参考以下文章