简单题
Leetcode: 9 回文数
简单的想法就是将数字转化为字符进行比较,但是这样占空间
class Solution {
public:
bool isPalindrome(int x) {
if(x < 0) return false;
if(x < 10 && x >= 0) return true;
vector<int> num;
while(x > 9){
num.push_back(x%10);
x = x/10;
}
num.push_back(x);
int i = 0;
int j = num.size() - 1;
while(i <= j){
if(num[i] == num[j]){
i++;
j--;
}
else{
return false;
}
}
return true;
}
};
官方的题解为
时间复杂度O(longn)
空间复杂度为O(1)
class Solution {
public:
bool isPalindrome(int x) {
// 特殊情况:
// 如上所述,当 x < 0 时,x 不是回文数。
// 同样地,如果数字的最后一位是 0,为了使该数字为回文,
// 则其第一位数字也应该是 0
// 只有 0 满足这一属性
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revertedNumber = 0;
while (x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
return x == revertedNumber || x == revertedNumber / 10;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/palindrome-number/solutions/281686/hui-wen-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Leetcode: 268 丢失的数字
用哈希表,查找数字在不在里面
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
unordered_set<int> L1(nums.begin(),nums.end());
int i = 0;
for(i = 0; i <= n; i++){
if(L1.find(i) == L1.end())
break;
}
return i;
}
};
或者也可以直接用排序
class Solution {
public:
int missingNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());
int n = nums.size();
for (int i = 0; i < n; i++) {
if (nums[i] != i) {
return i;
}
}
return n;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/missing-number/solutions/1085105/diu-shi-de-shu-zi-by-leetcode-solution-naow/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
public:
int missingNumber(vector<int>& nums) {
int res = 0;
int n = nums.size();
for (int i = 0; i < n; i++) {
res ^= nums[i];
}
for (int i = 0; i <= n; i++) {
res ^= i;
}
return res;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/missing-number/solutions/1085105/diu-shi-de-shu-zi-by-leetcode-solution-naow/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Leetcode: 771 宝石与石头
直接无脑hash
class Solution {
public:
int numJewelsInStones(string jewels, string stones) {
unordered_set<char> L1(jewels.begin(),jewels.end());
int count = 0;
for(int i = 0; i < stones.size(); i++){
if(L1.find(stones[i]) != L1.end()){
count++;
}
}
return count;
}
};
Leetcode: 面试题0801 三步问题
第一种解法,简单的动态规划dp,是爬楼梯问题的扩展。
时间复杂度O(N)
空间复杂度O(1)
class Solution {
public:
int waysToStep(int n) {
int a=1,b=2,c=4,i;
for(i=2;i<=n;i++){
long long t=(a+b)%1000000007;
t=(t+c)%1000000007;
a=b;
b=c;
c=t;
}
return a;
}
};
第二种解法快速幂
就是代码写起来比较难,所以还是建议用动态规划简单求解,但是面试的时候可以说这个方法。
Leetcode:面试题0810 颜色填充
把相邻的元素染成一个颜色。
深度搜索和广度搜索的经典题目,在之前的练习中是岛屿题目。
方法一:广度优先搜索
我们从给定的起点开始,进行广度优先搜索。每次搜索到一个方格时,如果其与初始位置的方格颜色相同,就将该方格加入队列,并将该方格的颜色更新,以防止重复入队。
时间和空间复杂度为O(NM)
class Solution {
public:
const int dx[4] = {1, 0, 0, -1};
const int dy[4] = {0, 1, -1, 0};
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
int currColor = image[sr][sc];
if (currColor == newColor) {
return image;
}
int n = image.size(), m = image[0].size();
queue<pair<int, int>> que;
que.emplace(sr, sc);
image[sr][sc] = newColor;
while (!que.empty()) {
int x = que.front().first, y = que.front().second;
que.pop();
for (int i = 0; i < 4; i++) {
int mx = x + dx[i], my = y + dy[i];
if (mx >= 0 && mx < n && my >= 0 && my < m && image[mx][my] == currColor) {
que.emplace(mx, my);
image[mx][my] = newColor;
}
}
}
return image;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/color-fill-lcci/solutions/1790727/yan-se-tian-chong-by-leetcode-solution-ejum/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
方法二:深度优先搜索
时间和空间复杂度为O(NM)
class Solution {
public:
const int dx[4] = {1, 0, 0, -1};
const int dy[4] = {0, 1, -1, 0};
void dfs(vector<vector<int>>& image, int x, int y, int color, int newColor) {
if (image[x][y] == color) {
image[x][y] = newColor;
for (int i = 0; i < 4; i++) {
int mx = x + dx[i], my = y + dy[i];
if (mx >= 0 && mx < image.size() && my >= 0 && my < image[0].size()) {
dfs(image, mx, my, color, newColor);
}
}
}
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
int currColor = image[sr][sc];
if (currColor != newColor) {
dfs(image, sr, sc, currColor, newColor);
}
return image;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/color-fill-lcci/solutions/1790727/yan-se-tian-chong-by-leetcode-solution-ejum/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
从代码简单程度来看,深度优先搜索的代码写起来简单一点。
Leetcode: 158 内存管理
第一想到是用哈希map来做
class Solution {
public:
int inventoryManagement(vector<int>& stock) {
unordered_map<int, int> mp;
for(int n : stock){
mp[n]++;
if(mp[n] > stock.size()/2){
return n;
}
}
return 0;
}
};
基于上述的推论,有摩尔法如下:
class Solution {
public:
int inventoryManagement(vector<int>& stock) {
int x = 0, votes = 0;
for(int num : stock){
if(votes == 0) x = num;
if(num == x) votes++;
else votes--;
}
return x;
}
};
Leetcode: LCR120 寻找文件副本
class Solution {
public:
int findRepeatDocument(vector<int>& documents) {
unordered_map<int, int> mp;
for(int n : documents){
mp[n]++;
if(mp[n] > 1){
return n;
}
}
return 0;
}
};
中等题
Leetcode: 6 Z字形变换
算法基本流程
public:
string convert(string s, int numRows) {
if(numRows < 2)
return s;//处理特殊情况
vector<string> rows(numRows);
int i = 0, flag = -1;
for(char c: s){//把字符串的元素加到对应的行中
rows[i].push_back(c);
if(i == 0 || i == numRows - 1)
flag = -flag;//flag反转,进行模拟
i += flag;
}
string res;
for(const string &row : rows)
res += row;//收集最后的结果
return res;
}
};
Leetcode:48 旋转矩阵
第一种方法是使用另一个空白的矩阵来存储旋转之后的结果,但是题目要求不能使用,所以要求我们要原地旋转。
使用一个零时变量temp来存储要旋转的位置,保存原来的旋转过去位置的值,然后把那个值放到下一个位置。
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = 0; i < n / 2; ++i) {
for (int j = 0; j < (n + 1) / 2; ++j) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];//这是最主要的旋转公式
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = temp;
}
}
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/rotate-image/solutions/526980/xuan-zhuan-tu-xiang-by-leetcode-solution-vu3m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
方法三是使用旋转的方法,先水平翻转,然后对角线翻转。
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
// 水平翻转
for (int i = 0; i < n / 2; ++i) {
for (int j = 0; j < n; ++j) {
swap(matrix[i][j], matrix[n - i - 1][j]);
}
}
// 主对角线翻转
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
swap(matrix[i][j], matrix[j][i]);
}
}
}
};
从代码难度上,更喜欢第三种解法。
Leetcode: 92 反转链表2
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
int slow = 0;
ListNode* dymmyhead = new ListNode(0);
dymmyhead->next = head;
ListNode* pre = dymmyhead;
for(int i = 0; i < left - 1; i++){
pre = pre->next;//找到开始旋转的起始位置
}
ListNode* cur = pre->next;//找到需要断开的位置
ListNode* node;
for(int i = 0; i < right - left; i++){
node = cur->next;
cur->next = node->next;
node->next = pre->next;
pre->next = node;
}
return dymmyhead->next;
}
};
Leetcode:187 重复的DNA序列
我们可以用一个哈希表统计 sss 所有长度为 101010 的子串的出现次数,返回所有出现次数超过 10的子串。为了不重复记录数组,只保存出现==2的字串。
class Solution {
const int L = 10;
public:
vector<string> findRepeatedDnaSequences(string s) {
vector<string> ans;
unordered_map<string, int> cnt;
int n = s.length();
for (int i = 0; i <= n - L; i++) {
string sub = s.substr(i, L);
cnt[sub]++;
if (cnt[sub] == 2) {
ans.push_back(sub);
}
}
return ans;
}
};
Leetcode: 852 山脉数组的峰值索引
暴力做法就是找到最大的那个数值就可以。
但是要求复杂度在O(logN),所以可以使用二分法来实现。
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
int left = 0, right = arr.size() - 1;
int result = 0;
while(left <= right){
int mid = left + (right - left)/2;
if(arr[mid]>arr[mid-1]&&arr[mid]>arr[mid+1]){
result = mid;
break;
}
else if(arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1]) left = mid;
else if(arr[mid] > arr[mid + 1] && arr[mid] < arr[mid - 1]) right = mid;
}
return result;
}
};
Leetcode: 22 括号生成
基本的回溯内容。
需要进一步复习。
class Solution {
public:
vector<string> ans;
vector<string> generateParenthesis(int n) {
backtracing(n,"", n, n);
return ans;
}
void backtracing(int n, string str, int left, int right){
if(left == 0 && right == 0){
ans.push_back(str);
return;
}
if(left <= right){//剩余的左括号一定要小于等于右括号
if(left > 0) backtracing(n, str + '(', left - 1, right);
if(right > 0) backtracing(n, str + ')', left, right - 1);
}
else return;
}
};
Leetcode: 678 有效的括号
第一种方法,两次遍历。
两次遍历 第一次遍历:从前往后遍历确定')',排除类似'))'的情况; 第二次遍历:从后往前遍历确定'(',排除类似'(('的情况; 其余的都符合
class Solution {
public:
bool checkValidString(string s) {
int n = s.length();
int l = 0, m = 0;
for(int i = 0; i < n; ++i){
if(s[i] == '('){
l++;
}
else if(s[i] == ')'){
l--;
}
else{
m++;
}
if(l < 0){
m--;
l++;
}
if(m < 0){
return false;
}
}
int r = 0;
m = 0;
for(int i = n-1; i >=0; --i){
if(s[i] == ')'){
r++;
}
else if(s[i] == '('){
r--;
}
else{
m++;
}
if(r < 0){
m--;
r++;
}
if(m < 0){
return false;
}
}
return true;
}
};
class Solution {
public:
bool checkValidString(string s) {
int minCount = 0, maxCount = 0;
int n = s.size();
for (int i = 0; i < n; i++) {
char c = s[i];
if (c == '(') {
minCount++;
maxCount++;
} else if (c == ')') {
minCount = max(minCount - 1, 0);
maxCount--;
if (maxCount < 0) {
return false;
}
} else {
minCount = max(minCount - 1, 0);
maxCount++;
}
}
return minCount == 0;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/valid-parenthesis-string/solutions/992347/you-xiao-de-gua-hao-zi-fu-chuan-by-leetc-osi3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
当然括号匹配的问题一般都可以用栈来解决
class Solution {
public:
bool checkValidString(string s) {
stack<int> leftStack;
stack<int> asteriskStack;
int n = s.size();
for (int i = 0; i < n; i++) {
char c = s[i];
if (c == '(') {
leftStack.push(i);
} else if (c == '*') {
asteriskStack.push(i);
} else {
if (!leftStack.empty()) {
leftStack.pop();
} else if (!asteriskStack.empty()) {
asteriskStack.pop();
} else {
return false;
}
}
}
while (!leftStack.empty() && !asteriskStack.empty()) {
int leftIndex = leftStack.top();
leftStack.pop();
int asteriskIndex = asteriskStack.top();
asteriskStack.pop();
if (leftIndex > asteriskIndex) {
return false;
}
}
return leftStack.empty();
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/valid-parenthesis-string/solutions/992347/you-xiao-de-gua-hao-zi-fu-chuan-by-leetc-osi3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Leetcode:215 数组中的第K个最大元素
第一种方法就是很简单的排序然后取n-k个元素就好。
第二种方法:堆排序
建立一个大根堆,做 k−1次删除操作后堆顶元素就是我们要找的答案。
时间复杂度O(nlogn)
空间复杂度O(N)
class Solution {
public:
void maxHeapify(vector<int>& a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;
if (l < heapSize && a[l] > a[largest]) {
largest = l;
}
if (r < heapSize && a[r] > a[largest]) {
largest = r;
}
if (largest != i) {
swap(a[i], a[largest]);
maxHeapify(a, largest, heapSize);
}
}
void buildMaxHeap(vector<int>& a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {
maxHeapify(a, i, heapSize);
}
}
int findKthLargest(vector<int>& nums, int k) {
int heapSize = nums.size();
buildMaxHeap(nums, heapSize);
for (int i = nums.size() - 1; i >= nums.size() - k + 1; --i) {
swap(nums[0], nums[i]);
--heapSize;
maxHeapify(nums, 0, heapSize);
}
return nums[0];
}
};
Leetcode: 621 任务调度器
时间复杂度 O(nlogn),空间复杂度 O(1)
class Solution {
public:
int leastInterval(vector<char>& tasks, int n) {
int len=tasks.size();
vector<int> vec(26);
for(char c:tasks) ++vec[c-'A'];
sort(vec.begin(),vec.end(),[](int& x,int&y){return x>y;});
int cnt=1;
while(cnt<vec.size()&&vec[cnt]==vec[0]) cnt++;
return max(len,cnt+(n+1)*(vec[0]-1) );
}
};