前缀和
前缀和是一个数组,多次询问区间和的时候,空间换时间
前缀和从num[1]开始存,num[0]空出来防止访问越界
7. 整数反转
class Solution {
public:
int reverse(int x) {
int ans = 0;
while (x) {
// 输出0的情况特判
if (ans > INT_MAX / 10 || ans < INT_MIN / 10 || // ans大或小:*10超出上界或下界
ans == INT_MAX / 10 && x % 10 > 7 || // ans大:加上个位超出上界
ans == INT_MIN / 10 && x % 10 < -8 // ans小:加上个位超出下界
) return 0;
ans = ans * 10 + x % 10;
x /= 10;
}
return ans;
}
};
- 假设环境不允许存储 64 位整数(有符号或无符号),意思是只能使用int型(区别于第9题)
- int范围:-2147483648 ~ 2147483647[-231 ~ 231-1]
9. 回文数
class Solution {
public:
bool isPalindrome(int x) {
if (x < 0) return false;
long long raw = x, t = 0;
while (x) {
t = t * 10 + x % 10;
x /= 10;
}
return t == raw;
}
};
- int 反转防止越界,必须用 long long 定义 t
13. 罗马数字转整数
class Solution {
public:
int romanToInt(string s) {
int ans = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'I') {
if (s[i + 1] == 'V' || s[i + 1] == 'X') { // 特殊规则的2种情况
ans += (s[i + 1] == 'V' ? 4 : 9); // 三目运算符
i++; // i后移
} else {
ans += 1;
}
} else if (s[i] == 'X') {
if (s[i + 1] == 'L' || s[i + 1] == 'C') {
ans += (s[i + 1] == 'L' ? 40 : 90);
i++;
} else {
ans += 10;
}
} else if (s[i] == 'C') {
if (s[i + 1] == 'D' || s[i + 1] == 'M') {
ans += (s[i + 1] == 'D' ? 400 : 900);
i++;
} else {
ans += 100;
}
} else if (s[i] == 'V') {
ans += 5;
} else if (s[i] == 'L') {
ans += 50;
} else if (s[i] == 'D') {
ans += 500;
} else {
ans += 1000;
}
}
return ans;
}
};
- 用switch或 if 都可以实现
- if实现时用了三目运算符
14. 最长公共前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) { // vector<string> 可以理解为字符串动态数组
if (strs.size() == 0) return ""; // 返回空串
string ans = strs[0]; // ans赋值为第一个串
for (int i = 1; i < strs.size(); i++) {
string t = ans;
ans = ""; // 置为空串
for (int j = 0; j < strs[i].size() && j < t.size(); j++) { // 两个串中必须有字符
if (strs[i][j] == t[j]) {
ans += t[j];
} else {
break;
}
}
if (ans == "") break; // 某一轮后ans串为空,不必判断后续
}
return ans;
}
};
- 字符串为空,访问下标为0的字符串会报错
- j是按位遍历第i个字符串,同时j要小于现有的t的长度
26. 删除有序数组中的重复项
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0) return 0;
// 第一个肯定不会重复
int last = nums[0], pos = 1; // last上一个存好的数字,pos当前存到了第几个数
for (int i = 1; i < nums.size(); i++) {
if (nums[i] != last) {
last = nums[i];
nums[pos] = nums[i];
pos++;
}
}
return pos;
}
};
- 第一个数一定不会重复,删掉后面的数即可
- 有序说明相等的数在一起,本题无序也可以,但是要保证相等的数在一起
27. 移除元素
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if (nums.size() == 0) return 0;
int pos = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != val) {
nums[pos] = nums[i];
pos++;
}
}
return pos;
}
};
- 遍历数组判断val,不是val的往前存
- 26,27题就是遍历一次的问题
35. 搜索插入位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
if (nums[nums.size() - 1] < target) return nums.size(); // 特判最大值<taregt
int l = 0, r = nums.size() - 1;
while (l != r) {
int mid = (l + r) / 2;
if (nums[mid] >= target) r = mid; // 返回第一个大于等于它的值的下标,00001111
else l = mid + 1;
}
return l;
}
};
- 返回第一个大于等于它的位置
- 添加一个特判,大于数组最大值时输出nums.size()
- 添加一个极大值在数组尾部,进行二分
38. 外观数列
- 2个数组来回倒,通过 swap(a, b) 两个指针
- cnt计数
58. 最后一个单词的长度
- 思路:2个指针从后往前遍历,一个找到第一个不为 “” 的下标,另一个从当前位置继续找第一个为 ""的下标,长度是 r - l
- l 和 r 都初始化为-1
r 初始化为-1是:字符串只有1个字符时指向下标0,会产生歧义;出了循环 r 还为 -1,表示空串直接输出0
l 初始化为-1是:字符串只有1个单词时,l 值还是为-1,充当下标0前面的“”(空格) - 本题要求输出的话有一个讨巧的方法:while 循环 cin 时,最后直接输出 s.size()
53. 最大子序和
- 经典动态规划
- ans[i] 以 i 结尾的最大连续和,不需要维护一个数组,只需要维护一个变量就够了
66. 加一
- 处理进位