《高级数据结构》-leetcode刷题课
刷题建议
《高级数据结构》课程结束了,leetcode才是算法人员的第二春(坚持刷题,坚持数据结构与算法思维》,至少坚持每天一个题目
- leetcode的简单题一般锻炼代码能力
- leetcode的难题目一般锻炼数据结构与算法思维
8:字符串转整型
// 代码核心:越界处理,pre_max和d
class Solution {
public:
int myAtoi(string s) {
int ind = 0, num = 0, flag = 1;
int pre_max = INT_MAX / 10; // 整型能表示的最大值前面部分 -> 越界判断
int d = INT_MAX % 10;
// 去除前置空格
while (ind < s.size() && s[ind] == ' ') ++ ind;
// 正负数判断
if (s[ind] == '+') flag = 1, ++ind;
else if (s[ind] == '-') flag = -1, ++ind;
while (ind < s.size()) {
// 数字是否合理
if (s[ind] < '0' || s[ind] > '9') break;
// num需要判断是否越界
if (num > pre_max || (num == pre_max && s[ind] - '0' > d)) {
if (flag == -1) return INT_MIN;
return INT_MAX;
}
num = num * 10 + (s[ind] - '0');
++ind;
}
return num * flag;
}
};
13:罗马数字转整数
class Solution {
public:
int getValue(char ch) {
switch(ch) {
case 'I' : return 1;
case 'V' : return 5;
case 'X' : return 10;
case 'L' : return 50;
case 'C' : return 100;
case 'D' : return 500;
case 'M' : return 1000;
}
return 0;
}
int romanToInt(string s) {
int num = 0;
for (int i = 0; s[i]; i++) {
// 位权
num += getValue(s[i]);
// ? 位权判断
if (i && getValue(s[i]) > getValue(s[i -1])) {
num -= 2 * getValue(s[i - 1]); // 2倍
}
}
return num;
}
};
14:最长公共前缀
class Solution {
public:
string Compare(string &a, string &b) {
string ret = "";
for (int i = 0; a[i]; i++) {
if (i == b.size()) return ret;
if (a[i] != b[i]) return ret;
ret += a[i];
}
return ret;
}
string longestCommonPrefix(vector<string>& strs) {
string ret = strs[0];
for (int i = 1; i < strs.size(); i++) {
ret = Compare(ret, strs[i]);
}
return ret;
}
};
28:strSTR()
利用sunday算法实现单模匹配
// 单模匹配问题:kmp,sunday,kmp,shift-and,暴力,怎么进行算法选择
// 用sunday实现
class Solution {
public:
// needle 模式串
int strStr(string haystack, string needle) {
int ind[128]; // 每种字符出现在倒数多少位
for (int i = 0; i < 128; i++) ind[i] = needle.size();
// 扫描模式串的每一位
for (int i = 0; needle[i]; i++) ind[needle[i]] = needle.size() - i;
// 设置匹配变量 i
int i = 0;
// 匹配操作
while (i + needle.size() <= haystack.size()) {
int flag = 1; // 匹配成功
// j
for (int j = 0; needle[j]; j++) {
if (haystack[i + j] == needle[j]) continue;
flag = 0; // 匹配不成功
break;
}
// 结果判断
if (flag) return i; // 完美匹配
i += ind[haystack[i +needle.size()]]; // 向后调整i指针位置;黄金对齐点位置
}
return -1; // 在文本串中找不到模式串
}
};
- 尝试用shift-and解决该问题
– 问题:超INT怎么办? -> 模拟一个数据类型;bitset;高精度思想;二进制位标记
36:有效的数独
// 核心1:二进制标记法
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
int x[9] = {0}, y[9] = {0}, z[9] = {0}; //
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') continue;
int d = board[i][j] - '0';
// 出现过则直接 return flase;
if (x[i] & (1 << d)) return false;
if (y[j] & (1 << d)) return false;
// 核心2: 宫格编号 0-8
if (z[i / 3 * 3 + j / 3] & (1 << d)) return false; //
x[i] |= (1 << d);
y[j] |= (1 << d);
z[i / 3 * 3 + j / 3] |= (1 << d);
}
}
return true;
}
};
58:最后一个单词的长度
class Solution {
public:
int lengthOfLastWord(string s) {
// 从后往前找
int p1 = s.size() - 1, p2;
while (p1 >= 0 && s[p1] == ' ') --p1; // p1:最后一个字母
p2 = p1; // p2最后一个单词的首字母前一位
while (p2 >= 0 && s[p2] != ' ') --p2;
return p1 - p2;
}
};
125:验证回文串
class Solution {
public:
bool is_alpha(char ch) {
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
}
bool is_digit(char ch) {
return ch <= '9' && ch >= '0';
}
bool isPalindrome(string s) {
int l = 0, r = s.size() - 1;
while (l < r) {
while (l < r && !(is_alpha(s[l]) || is_digit(s[l]))) ++l;
while (l < r && !(is_alpha(s[r]) || is_digit(s[r]))) --r;
// 技巧:大写变成小写
if (s[l] <= 'Z' && s[l] >= 'A') s[l] += 32;
if (s[r]<= 'Z' && s[r] >= 'A') s[r] += 32;
if (s[l] - s[r]) return false;
++l, --r;
}
return true;
}
};
165:比较版本号
// 简单的题目锻炼的是 编码能力,难的题一般都是算法能力
// 技巧点:1.01 vs 1.0 -> 101 vs 100
class Solution {
public:
void getValue(string &s, int &i, int &val) {
val = 0;
while (s[i] && s[i] != '.') val = val * 10 + (s[i++] - '0');
if (s[i]) ++i;
return ;
}
int compareVersion(string version1, string version2) {
int i = 0, j = 0; // 位数
int val1, val2; // 作为传出参数:除去 '.'
while (version1[i] || version2[j]) {
getValue(version1, i, val1);
getValue(version2, j, val2);
if (val1 - val2) return (val1 < val2 ? - 1 : 1);
}
return 0;
}
};
205:同构字符串
// 记录两种映射:s->t t->s, 保证一一对应
class Solution {
public:
bool isIsomorphic(string s, string t) {
if (s.size() - t.size()) return false;
int st[128] = {0}, ts[128] = {0}; // 映射数组
for (int i = 0; s[i]; i++) {
//s->t 的映射建立
if (st[s[i]] == 0) st[s[i]] = t[i]; //建立映射
else if (t[i] - st[s[i]]) return false; //出现冲突
// t->s 的映射建立
if (ts[t[i]] == 0) ts[t[i]] = s[i];
else if (s[i] - ts[t[i]]) return false;
}
return true;
}
};
242:有效的字母异构词
// 字母组成一样,但是组成一样 -> 计数排序(字母出现的次数)
class Solution {
public:
bool isAnagram(string s, string t) {
if (s.size() - t.size()) return false;
int cnt[128] = {0};
for (int i = 0; s[i]; i++) cnt[s[i]] += 1;
for (int i = 0; t[i]; i++) {
cnt[t[i]] -= 1;
if (cnt[t[i]] == -1) return false;
}
return true;
}
};
290:单词规律
// 与单词同构词是一样的,都是映射关系的处理 ?
class Solution {
public:
void getNextWord(string &s, int &j, string &t) {
t = ""; // 清空t串
while (s[j] && s[j] == ' ') ++j; // 吞掉空格
while (s[j] && s[j] != ' ') t += s[j++]; // 提取下一个单词
return ;
}
bool wordPattern(string p, string s) {
string ps[128]; // 存储p->s的映射
unordered_map<string, char> sp;//hash:存储p->s的映射
string t;
int j = 0;
// 扫描pattern的每一位
for (int i = 0; p[i]; i++) {
getNextWord(s, j, t); // t获得s的下一个单词
if (t == "" ) return false; // s和p串长度不同
// 之前没有映射,创建映射
if (ps[p[i]] == "") ps[p[i]] = t;
else if (ps[p[i]] != t) return false; // 之前映射与现在不是一对
// 同上
if (sp.find(t) == sp.end()) sp[t] = p[i];
else if (sp[t] != p[i]) return false;
}
if (j != s.size()) return false;
// s串应该要处理到最后一位
return true;
}
};
344:反转字符串
class Solution {
public:
void reverseString(vector<char>& s) {
// 设置头尾两个指针,一起往中间走(翻转字符串,翻转数组)
for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
swap(s[i], s[j]);
}
return ;
}
};
345:反转字符串的元音字母
class Solution {
public:
bool is_valid(char ch) {
if (ch < 97) ch += 32;
switch (ch) {
case 'a' :
case 'e' :
case 'i' :
case 'u' :
case 'o' : return true;
}
return false;
}
string reverseVowels(string s) {
for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
// ?
while (i < j && !is_valid(s[i])) ++i;
while (i < j && !is_valid(s[j])) --j;
swap(s[i], s[j]);
}
return s;
}
};
383:赎金信
// 异位字符串
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int cnt[128] = {0};
for (int i = 0; magazine[i]; i++) cnt[magazine[i]] += 1;
for (int i = 0; ransomNote[i]; i++) {
cnt[ransomNote[i]] -= 1;
if (cnt[ransomNote[i]] == -1) return false;
}
return true;
}
};
- 练习题:leetcode387