189. 轮转数组
class Solution {
public:
void rotate(vector<int>& nums, int k) {
k = k % nums.size();
reverse(nums.begin(), nums.end());
reverse(nums.begin(), nums.begin() + k);
reverse(nums.begin() + k, nums.end());
}
};
73. 矩阵置零
vector、map、set都可以用find函数,但是vector和后两个的用法不同
自己写的
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
if(matrix.size() == 0) return;
vector<int> seti;
vector<int> setj;
for(int i = 0; i < matrix.size(); i ++){
for(int j = 0; j < matrix[0].size(); j ++){
if(matrix[i][j] == 0){
seti.push_back(i);
setj.push_back(j);
}
}
}
for(int i = 0; i < matrix.size(); i ++){
for(int j = 0; j < matrix[0].size(); j ++){
if(find(seti.begin(), seti.end(), i) != seti.end()) matrix[i][j] = 0;
if(find(setj.begin(), setj.end(), j) != setj.end()) matrix[i][j] = 0;
}
}
return;
}
};
560. 和为 K 的子数组
暴力法(通过但是超时)
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int res = 0;
if(nums.size() == 0) return k == 0 ? 1 : 0;
for(int i = 0; i < nums.size(); i++){
int sum = 0;
for(int j = i; j >= 0; j--){//这里正着遍历也行
sum += nums[j];
if(sum == k) res ++;
}
}
return res;
}
};
实际上想让用前缀做
=====待补充=======
11. 盛最多水的容器
暴力(不能完全通过)
class Solution {
public:
int maxArea(vector<int>& height) {
int legth = 0;
int h = 0;
int res = 0;
if(height.size() == 0) return 0;
for(int i = 0; i < height.size(); i++){
for(int j = i; j < height.size(); j++){
legth = j - i;
h = min(height[i], height[j]);
res = res > legth * h ? res : legth * h;
}
}
return res;
}
};
双指针法
我写的不太对:28/63
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0;
int right = height.size() - 1;
int res = water(left, right, height[left], height[right]);
while(left < right){
if(water(left + 1, right, height[left + 1], height[right]) > water(left, right, height[left], height[right])) {
res = water(left + 1, right, height[left + 1], height[right]);
left += 1;
continue;
}
if(water(left, right - 1, height[left], height[right - 1]) > water(left, right, height[left], height[right])) {
res = water(left, right - 1, height[left], height[right - 1]);
right -= 1;
continue;
}
break;
}
return res;
}
private:
int water(int left, int right, int lefth, int righth){
int h = min(lefth, righth);
int l = right - left;
//cout << right << left << endl;
int res = h * l;
return res;
}
};
正确的在这里:height[left]和height[right]谁小移动谁!因为移动长板的话,就算下一个更长,因为另一边是短板,水量也只能减少!
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0;
int right = height.size() - 1;
int res = 0;
while(left < right){
if(height[left] < height[right]) {
res = res > height[left] * (right - left) ? res : height[left] * (right - left);
left += 1;
}else{
res = res > height[right] * (right - left) ? res : height[right] * (right - left);
right -=1;
}
}
return res;
}
};
2520. 统计能整除数字的位数
这种把每一数位提取出来的办法值得记一下
class Solution {
public:
int countDigits(int num) {
int t = num, res = 0;
while (t) {
if (num % (t % 10) == 0) {
res += 1;
}
t /= 10;
}
return res;
}
};
我的方法也许用时比较久
class Solution {
public:
int countDigits(int num) {
int val;
int res = 0;
string str = to_string(num);
for(int i = 0; i < str.size(); i++){
val = str[i] - '0';
if(num % val == 0) res++;
}
return res;
}
};
2558. 从数量最多的堆取走礼物
wow用到了priority_queue优先队列,维护最大堆!
class Solution {
public:
long long pickGifts(vector<int>& gifts, int k) {
priority_queue<int> q(gifts.begin(), gifts.end());
while(k--){
int x = q.top();
q.pop();
q.push(sqrt(x));
}
long long res = 0;
while(!q.empty()){
res += q.top();
q.pop();
}
return res;
}
};
class Solution {
public:
int countPoints(string rings) {
vector<vector<int>> vec(10,vector<int>(3));
int res = 0;
for(int i = 0; i < rings.size(); i = i + 2){
if(rings[i] == 'R'){
vec[rings[i+1]-'0'][0] = 1;
}
if(rings[i] == 'G'){
vec[rings[i+1]-'0'][1] = 1;
}
if(rings[i] == 'B'){
vec[rings[i+1]-'0'][2] = 1;
}
}
int sum = 0;
for(int i = 0; i < 10; i++){
for(int j = 0; j < 3; j++){
sum += vec[i][j];
}
if(sum == 3) res++;
sum = 0;
}
return res;
}
};
318. 最大单词长度乘积
【需要回顾】
考虑位运算,位运算的优先级低所以注意加括号!!
注意数组的定义和初始化
max用的时候也许需要(int)(--)
class Solution {
public:
int maxProduct(vector<string>& words) {
int n = words.size();
int res = 0;
//int mask[n]={0};会报错,如果n是具体的数那ok
int mask[n];
memset(mask, 0 , sizeof(mask));
for(int i = 0; i < n; i++){
for(char c : words[i]){
mask[i] |= 1 << (c - 'a');//取或
}
for(int j = 0; j < i; j++){
if((mask[i] & mask[j]) == 0){//不加括号通不过
res = max(res, (int)(words[i].size()*words[j].size()));//不加int通不过
//if(res < words[i].size()*words[j].size()) res = words[i].size()*words[j].size();
}
}
}
return res;
}
};
2586. 统计范围内的元音字符串数
class Solution {
public:
int vowelStrings(vector<string>& words, int left, int right) {
int res = 0;
for(int i = left; i <= right; i++){
string str = words[i];
int size = words[i].size();
if(str[0] == 'a' || str[0] == 'e' || str[0] == 'i' || str[0] == 'o' || str[0] == 'u')
if(str[size-1] == 'a' || str[size-1] == 'e' || str[size-1] == 'i' || str[size-1] == 'o' || str[size-1] == 'u')
res++;
}
return res;
}
};
【待做...】
2609. 最长平衡子字符串
class Solution {
public:
int findTheLongestBalancedSubstring(string s) {
int count[2] = {0, 0};
int res = 0;
if(s.size() < 2) return 0;
if(s[0] == '0') count[0]++;
for(int i = 1 ; i < s.size(); i++){
if(s[i-1] == '1' && s[i] =='0'){
int restemp = min(count[0],count[1]);
res = max(res, restemp);
count[0] = 1;
count[1] = 0;
}else if(s[i] == '0'){
count[0]++;
}else if(s[i] == '1'){
count[1]++;
}else{};
}
int restemp = min(count[0],count[1]);
res = max(res, restemp);
return res * 2;
}
};
238. 除自身以外数组的乘积
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int product = 0;
vector<int> res;
vector<int> left(nums.size(), 1);
vector<int> right(nums.size(), 1);
left[0] = 1;//对于索引为0的元素,因为左侧没有元素,所以L(0)=1
for(int i = 1; i < nums.size(); i++){
left[i] = left[i - 1] * nums[i - 1];
}
right[nums.size() - 1] = 1;
for(int i = nums.size() - 2; i >= 0; i--){
right[i] = right[i + 1] * nums[i + 1];
}
for(int i = 0; i < nums.size(); i++){
res.push_back(left[i] * right[i]);
}
return res;
}
};
41. 缺失的第一个正数
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int res;
int n = nums.size();
for(int i = 0; i < n; i++){
if(nums[i] <= 0) nums[i] = n + 1;
}
for(int i = 0; i < n; i++){
int num = abs(nums[i]);
if(num < n + 1) nums[num - 1] = - abs(nums[num - 1]);
}
for(int i = 0; i < n; i++){
if(nums[i] > 0){
res = i + 1;
break;
}
}
return res;
}
};
739. 每日温度
暴力解法,无法通过所有案例
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
vector<int> res(temperatures.size(), 0);
for(int i = 0; i < temperatures.size(); i++){
for(int j = i + 1; j < temperatures.size(); j++){
if(temperatures[j] > temperatures[i]){
res[i] = j - i;
break;
}
}
}
return res;
}
};
【待补充..】
二维矩阵
240. 搜索二维矩阵 II
我的,每一行用二分法做,时间复杂度O(nlogn)这不是最简单的方法
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
for(int i = 0; i < matrix.size(); i++){
if(searchArray(matrix[i], target) == true) return true;
}
return false;
}
bool searchArray(vector<int>& array, int target){
int left = 0, right = array.size() - 1;
while(left <= right){
int middle = left + ((right - left)>>1);
if(array[middle] < target){
left = middle + 1;
}else if(array[middle] > target){
right = middle - 1;
}else return true;
}
return false;
}
};
一种很巧妙的方法,起点可以从左上角或者右下角开始,时间复杂度O(M+N)
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size() == 0) return false;
int i = 0, j = matrix[0].size() - 1;
while(i < matrix.size() && j >= 0){
if(matrix[i][j] > target){
j--;
}else if(matrix[i][j] < target){
i++;
}else return true;
}
return false;
}
};
48. 旋转图像
. - 力扣(LeetCode)注意对称的组合可以构成旋转的效果
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
upDown(matrix, n);
mainDiag(matrix, n);
}
void upDown(vector<vector<int>>& matrix, int n){
for(int i = 0; i < n / 2; i++){
for(int j = 0; j < n; j++){
int temp = matrix[i][j];
matrix[i][j] = matrix[n-1-i][j];
matrix[n-1-i][j] = temp;
}
}
}
void mainDiag(vector<vector<int>>& matrix, int n){
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
};
字符串反转相关的题目
列一下:
链表反转相关题目:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur = head;
ListNode* pre = NULL;
while(cur != nullptr){
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* cur = dummy;
left--;
for(int i = 0; i < left; i++){
cur = cur->next;
}
ListNode* pre = nullptr;
ListNode* beginLeft = cur;
cur = cur->next;
ListNode* beginRight = cur;
for(int i = 0; i < (right - left) && cur != nullptr; i++){
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
beginLeft->next = pre;
beginRight->next = cur;
head = dummy->next;
delete dummy;
return head;
}
};
记这个更好
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* p0 = dummy;
left--;
for(int i = 0; i < left; i++){
p0 = p0->next;
}
ListNode* pre = nullptr;
ListNode* cur = p0->next;
for(int i = 0; i < (right - left) && cur != nullptr; i++){
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
p0->next->next = cur;
p0->next = pre;
head = dummy->next;
delete dummy;
return head;
}
};
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* p0 = head;
int n = 0;
while(p0 != nullptr){
n++;
p0 = p0->next;
}
p0 = dummy;
while(n >= k){
n -= k;
ListNode* pre = nullptr;
ListNode* cur = p0->next;
for(int i = 0; i < k && cur != nullptr; i++){
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
ListNode* nxt = p0->next;
p0->next->next = cur;
p0->next = pre;
p0 = nxt;
}
head = dummy->next;
delete dummy;
return head;
}
};
美团面试考了
可以用双端队列;或者结合翻转链表来做。
80. 删除有序数组中的重复项 II
我的
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow = 0, fast = 0;
if(nums.size() < 3) return nums.size();
while(fast < nums.size()){
if(fast < nums.size() - 2){
if(nums[fast] != nums[fast + 2]){
nums[slow] = nums[fast];
slow ++;
}
}else{
nums[slow] = nums[fast];
slow ++;
}
fast ++;
}
return slow;
}
};
也可以
153. 寻找旋转排序数组中的最小值
用二分法,注意边界条件啊
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size() == 1) return nums[0];
int left = 0, right = nums.size() - 1;
while(left < right){
int middle = left + ((right - left) >> 1);
if(nums[middle] > nums[right]){
left = middle + 1;
}else if(nums[middle] <= nums[right]){
right = middle;
}
}
return nums[left];
}
};
154. 寻找旋转排序数组中的最小值 II
在上一题的基础上只是多了nums[middle] == nums[right]条件下的判断,这种情况下只需要让right左移就好。
class Solution {
public:
int findMin(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while(left < right){
int middle = left + ((right - left) >> 1);
if(nums[middle] > nums[right]){
left = middle + 1;
}else if(nums[middle] < nums[right]){
right = middle;
}else right--;
}
return nums[left];
}
};
====代码随想录中的附加题目====
1365. 有多少小于当前数字的数字
我的:
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> numsBackup(nums.begin(), nums.end());
vector<int> res;
sort(numsBackup.begin(), numsBackup.end());
unordered_map<int,int> map;
for(int i = 0; i < nums.size(); i++){
if(map.find(numsBackup[i]) == map.end()) map[numsBackup[i]] = i;
else map[numsBackup[i]] = min(map[numsBackup[i]], i);
}
for(int i = 0; i < nums.size(); i++){
res.push_back(map[nums[i]]);
}
return res;
}
};
改善1:第一个for循环用倒序遍历更好,这样可以找到相同元素的最小排序索引
for(int i = nums.size() - 1; i >= 0; i--){
// if(map.find(numsBackup[i]) == map.end()) map[numsBackup[i]] = i;
// else
map[numsBackup[i]] = i;
}
改善2:可以不用定义res向量,直接在numsBackup数组里覆盖。
改善3:题目中限制了0 <= nums[i] <= 100,所以可以用数组而不是map来存排序索引
改善后:
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> numsBackup(nums.begin(), nums.end());
sort(numsBackup.begin(), numsBackup.end());
int sortArray[101];
for(int i = nums.size() - 1; i >= 0; i--){
sortArray[numsBackup[i]] = i;//sortArray索引代表数字,值代表排序索引
}
for(int i = 0; i < nums.size(); i++){
numsBackup[i] = sortArray[nums[i]];
}
return numsBackup;
}
};
941. 有效的山脉数组
我的丑陋代码,标志位狂魔+面向案例编程..
class Solution {
public:
bool validMountainArray(vector<int>& arr) {
int flag = -1;
if(arr.size() < 3) return false;
for(int i = 1 ; i < arr.size(); i++){
int diff = arr[i] - arr[i - 1];
if(diff > 0 && flag == -1) flag = 0;
else if(diff < 0 && flag == 0) flag = 1;
else if(diff == 0) return false;
else if(diff < 0 && flag == -1) return false;
else if(diff > 0 && flag == 1) return false;
else{};
}
if(flag == 1) return true;
else return false;
}
};
双指针法不容易出错误~
class Solution {
public:
bool validMountainArray(vector<int>& arr) {
int left = 0;
int right = arr.size() - 1;
while(left < arr.size() - 1){
if(arr[left] < arr[left + 1]) left ++;
else break;
}
while(right > 0){
if(arr[right] < arr[right - 1]) right --;
else break;
}
if(left == arr.size() - 1 ||left == 0) return false;
if(right == arr.size() - 1 ||right == 0) return false;
if(left == right) return true;
else return false;
}
};
1207. 独一无二的出现次数
和官方一样(^-^)V
class Solution {
public:
bool uniqueOccurrences(vector<int>& arr) {
unordered_map<int,int> map;
unordered_set<int> set;
for(int i = 0; i < arr.size(); i++){
map[arr[i]]++;
}
for(auto count : map){
set.insert(count.second);
}
if(set.size() == map.size()) return true;
else return false;
}
};
724. 寻找数组的中心下标
要注意:
1、题意:左边=右边,不包括本下标对应的值
2、对于负数,如果%2的话,奇数是返回-1的,而不是1
我的
class Solution {
public:
int pivotIndex(vector<int>& nums) {
int sum = 0;
for(int n : nums) sum += n;
int leftSum = 0;
for(int i = 0; i < nums.size(); i++){
leftSum += nums[i];
if(abs(sum - nums[i]) % 2 == 1) continue;
if(leftSum - nums[i] == (sum - nums[i]) / 2) return i;
}
return -1;
}
};
34. 在排序数组中查找元素的第一个和最后一个位置
比代码随想录里面分别考虑左右边界要简单一点
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
if(nums.size() == 0) return {-1, -1};
while(left <= right && left < nums.size() && right >= 0){
//注意这条要先写,要不left就++,right就--了
if(nums[left] == target && nums[right] == target) return {left, right};
if(nums[left] < target) left++;
if(nums[right] > target) right--;
}
return {-1,-1};
}
};
922. 按奇偶排序数组 II
莫非我是天才?
class Solution {
public:
vector<int> sortArrayByParityII(vector<int>& nums) {
vector<int> res(nums.size());
int k = 0, m = 0;
for(int i = 0; i < nums.size(); i++){
if(nums[i] % 2 == 0) {
res[k * 2] = nums[i];
k++;
}
if(nums[i] % 2 == 1) {
res[m * 2 + 1] = nums[i];
m++;
}
}
return res;
}
};
35. 搜索插入位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(left <= right){
int middle = left + ((right - left) >> 1);
if(nums[middle] < target){
left = middle + 1;
}else if(nums[middle] > target){
right = middle - 1;
}else{
return middle;
}
}
return left;
}
};
205. 同构字符串
class Solution {
public:
bool isIsomorphic(string s, string t) {
unordered_map<char,char> maps2t;
unordered_map<char,char> mapt2s;
if(s.size() != t.size()) return false;
int n = s.size();
for(int i = 0; i < n; i++) {
if(maps2t.find(s[i]) == maps2t.end()) maps2t[s[i]] = t[i];
if(mapt2s.find(t[i]) == mapt2s.end()) mapt2s[t[i]] = s[i];
}
for(int i = 0; i < n; i++){
if(maps2t[s[i]] != t[i]) return false;
if(mapt2s[t[i]] != s[i]) return false;
}
return true;
}
};
1002. 查找共用字符
我的
class Solution {
public:
vector<string> commonChars(vector<string>& words) {
vector<string> vec;
int n = words.size();
vector<vector<int>> hash(26, vector<int>(n, 0));
unordered_map<char, int> map;
for(int i = 0; i < n; i++){
for(char c : words[i]){
hash[c-'a'][i]++;
}
}
for(int i = 0; i < 26; i++){
map[i + 'a'] = INT32_MAX;
for(int j = 0; j < n; j++){
map[i + 'a'] = min(map[i + 'a'], hash[i][j]);
}
}
for(auto m : map){
for(int i = 0; i < m.second; i++){
vec.push_back(string(1,m.first));
}
}
return vec;
}
};
844. 比较含退格的字符串
我用的栈,但是这种方法有点麻烦。字符串可以当栈用,而且两个字符串可以直接比较是否相同,比比较栈要方便。
我的(不好):
class Solution {
public:
bool backspaceCompare(string s, string t) {
stack<char> s1, t1;
s1 = transformStr(s);
t1 = transformStr(t);
return compareStr(s1, t1);
}
stack<char> transformStr(string str){
stack<char> st;
for(int i = 0; i < str.size(); i++){
if(str[i] != '#') st.push(str[i]);
else{
if(!st.empty()) st.pop();
}
}
return st;
}
bool compareStr(stack<char> st1, stack<char> st2){
while(true){
if(st1.empty() == true && st2.empty() == true) return true;
else if(st1.empty() == false && st2.empty() == true) return false;
else if(st1.empty() == true && st2.empty() == false) return false;
else if(st1.top() != st2.top()) return false;
else{
st1.pop();
st2.pop();
}
}
}
};
用字符串就行,好比较
class Solution {
public:
bool backspaceCompare(string s, string t) {
return transformStr(s) == transformStr(t);
}
string transformStr(string str){
string res;
for(char c : str){
if(c != '#') res.push_back(c);
else if(c == '#' && !res.empty()) res.pop_back();
else{}
}
return res;
}
};
129. 求根节点到叶节点数字之和
我的
class Solution {
public:
vector<vector<int>> pathSet;
vector<int> path;
int sumNumbers(TreeNode* root) {
if(root == nullptr) return 0;
path.push_back(root->val);
iter(root);
int res = calSum(pathSet);
return res;
}
int calSum(vector<vector<int>> vec){
int res = 0;
int elem = 0;
for(int i = 0; i < vec.size(); i ++){
for(int j = 0; j < vec[i].size(); j++){
elem += vec[i][j] * pow(10, (vec[i].size() - j - 1));
}
res += elem;
elem = 0;
}
return res;
}
void iter(TreeNode* node){
if(node->left == nullptr && node->right == nullptr){
pathSet.push_back(path);
return;
}
if(node->left){
path.push_back(node->left->val);
iter(node->left);
path.pop_back();
}
if(node->right){
path.push_back(node->right->val);
iter(node->right);
path.pop_back();
}
}
};
204. 计数质数
暴力解法【一些例子会超时】
class Solution {
public:
int countPrimes(int n) {
int count = 0;
if(n <= 2) return 0;
for(int i = 2; i < n; i ++){
if(isPrimes(i) == true) count++;
}
return count;
}
bool isPrimes(int a){
for(int i = 2; i * i <= a; i++){
if(a % i == 0) return false;
}
return true;
}
};
2. 两数相加
这种方法,不能通过全部,因为链表的长度<100,没有合适的数据类型,longlong都不够了
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
vector<int> vec1, vec2;
ListNode* cur = l1;
while(cur != nullptr){
vec1.push_back(cur->val);
cur = cur->next;
}
cur = l2;
while(cur != nullptr){
vec2.push_back(cur->val);
cur = cur->next;
}
long long num1 = vec2Num(vec1);
long long num2 = vec2Num(vec2);
long long sum = num1 + num2;
vector<int> vec3;
while(sum){
vec3.push_back(sum % 10);
sum /= 10;
}
ListNode* temp = new ListNode(0);
ListNode* head = new ListNode(0);
for(int i = 0; i < vec3.size(); i++){
ListNode* node = new ListNode(vec3[i]);
if(i != 0){
temp->next = node;
}else{
head = node;
}
temp = node;
}
return head;
}
long long vec2Num(vector<int>& vec){
long long res = 0;
for(int i = vec.size() - 1; i >= 0; i--){
res += vec[i];
res = res * 10;
}
return res / 10;
}
};
进位法可以避免上面的问题
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {//l1 l2就是head..
ListNode* myList = new ListNode(0);
//myList->val = 3;
ListNode* dummy = new ListNode(0);
dummy->next = myList;
ListNode* cur1 = l1;
ListNode* cur2 = l2;
int plus = 0;
int val;
while(cur1 != NULL || cur2 != NULL){
if(cur1 != NULL && cur2 != NULL) {
val = cur1->val + cur2->val + plus;
if(myList!=nullptr) myList->next = new ListNode(val % 10);
if(val >= 10) plus = val / 10;
else plus = 0;
cur1 = cur1->next;
cur2 = cur2->next;
myList = myList->next;
}else if(cur1 != NULL && cur2 == NULL){
val = cur1->val + plus;
if(myList!=nullptr) myList->next = new ListNode(val % 10);
if(val >= 10) plus = val / 10;
else plus = 0;
cur1 = cur1->next;
myList = myList->next;
}
else{
val = cur2->val + plus;
if(myList!=nullptr) myList->next = new ListNode(val % 10);
if(val >= 10) plus = val / 10;
else plus = 0;
cur2 = cur2->next;
myList = myList->next;
}
}
if(plus != 0)
{
myList->next = new ListNode(plus);
}
return dummy->next->next;
}
};
如果不限制空间复杂度n,这个题将会很简单。但是限制了,这样做
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> set;
for(int i = 0; i < nums.size(); i++){
set.insert(nums[i]);
}
int j = 0, res = 0;
for(int s : set){
if(set.find(s - 1) == set.end()){//如果是开头元素(找不到小一个的数)
int curnum = s;
int curres = 1;
while(set.find(curnum + 1) != set.end()){
curres++;
curnum++;
}
res = max(res, curres);
}
}
return res;
}
};
只需要对每个开头的数进行循环,直到这个序列不再连续,因此复杂度是O(n)。 以题解中的序列举例: [100,4,200,1,3,4,2] 去重后的哈希序列为: [100,4,200,1,3,2]
按照上面逻辑进行判断:
元素100是开头,因为没有99,且以100开头的序列长度为1
元素4不是开头,因为有3存在,过,
元素200是开头,因为没有199,且以200开头的序列长度为1
元素1是开头,因为没有0,且以1开头的序列长度为4,因为依次累加,2,3,4都存在。
元素3不是开头,因为2存在,过,
元素2不是开头,因为1存在,过。
双指针法
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0, left = 0, right = height.size() - 1, pre_max = 0, suf_max = 0;
while (left < right) {
pre_max = max(pre_max, height[left]);
suf_max = max(suf_max, height[right]);
ans += pre_max < suf_max ? pre_max - height[left++] : suf_max - height[right--];
}
return ans;
}
};
在每一步迭代中,我们比较
pre_max
和suf_max
的大小,然后决定是向左移动left
指针还是向右移动right
指针。这是因为我们总是希望先填满较低的一侧,因为这样可以确保后续接到的雨水不会溢出到已经填满的一侧。
滑动窗口,注意收缩窗口的条件
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> set;
int length = 0;
int j = 0;
for(int i = 0; i < s.size(); i++){
while(set.find(s[i]) != set.end()){
set.erase(s[j]);
j++;
}
set.insert(s[i]);
length = length>set.size()?length:set.size();
}
return length;
}
};