136. Single Number
1.位操作,用异或
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for(int num:nums){
res ^= num;
}
return res;
}
};
2.使用map(使用了不恒定的额外空间)
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int, int> map;
for(auto num:nums){
map[num]++;
}
for(auto val:map){
if(val.second == 1)
return val.first;
}
return -1;
}
};
3.排序后看前后两个元素是否一样,使用了恒定的额外空间
2. Add Two Numbers
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(-1);
ListNode* p = dummy;
ListNode* p1 = l1;
ListNode* p2 = l2;
int carry = 0; // 进位
while(p1 != NULL || p2 != NULL || carry != 0){
int val = carry;
if(p1 != NULL){
val += p1->val;
p1 = p1->next;
}
if(p2 != NULL){
val += p2->val;
p2 = p2->next;
}
carry = val/10;
val = val%10;
p->next = new ListNode(val);
p = p->next;
}
return dummy->next;
}
};
注意循环的时候要加上条件carry != 0
198. House Robber
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size() == 1) return nums[0];
vector<int> dp(nums.size(),0);
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
for(int i=2; i<nums.size(); i++){
dp[i] = max(dp[i-1], dp[i-2]+nums[i]);
}
return dp[nums.size()-1];
}
};
213. House Robber II
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size() == 1) return nums[0];
int res1 = robVal(nums, 0, nums.size()-2);
int res2 = robVal(nums, 1, nums.size()-1);
return max(res1, res2);
}
int robVal(vector<int>& nums, int first, int last){
if(first-last == 0) return nums[first];
vector<int> dp(nums.size(), 0);
dp[first] = nums[first];
dp[first+1] = max(nums[first], nums[first+1]);
for(int i=first+2; i<=last; i++){
dp[i] = max(dp[i-1], dp[i-2]+nums[i]);
}
return dp[last];
}
};
若为环形只有三种可能
1)不考虑第一个
2)不考虑最后一个
3)第一个和最后一个都不考虑(但在这道题中,这个一定是最小的,所以省略)
337. House Robber III
class Solution {
public:
int rob(TreeNode* root) {
vector<int> res = robTree(root);
return max(res[0], res[1]);
}
vector<int> robTree(TreeNode* cur){
if(cur == NULL) return vector<int>{0,0};
vector<int> left = robTree(cur->left);
vector<int> right = robTree(cur->right);
//偷了的值
int val1 = cur->val + left[0] +right[0];
//没偷的值
int val2 = max(left[0], left[1]) + max(right[0], right[1]);
return {val2, val1};
}
};
只能大概理解思路
思路:
这里的dp数组是记录每个节点的两个状态,0为没偷时的最大值,1为偷了时候的最大值。
因为这里要求一个节点偷与不偷的值,所以采用后续遍历(从下往上)
tips:这里写代码要注意一个小点,robTree函数return的值要符合自己的定义,即val2是没偷的,val1是偷的,所以要返回的是{val2, val1}, 不要写反了
18. 4Sum
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size(); i++){
if(nums[0] > target && nums[0] >= 0)
break;
if(i>0 && nums[i] == nums[i-1]){
continue;
}
for(int j=i+1; j<nums.size(); j++){
if(nums[i]+nums[j] > target && nums[i]+nums[j] >= 0){
break;
}
if(j>i+1 && nums[j] == nums[j-1]){
continue;
}
int left = j+1;
int right = nums.size()-1;
while(left < right){
if((long)nums[i]+nums[j]+nums[left]+nums[right] > target){
right--;
}else if((long)nums[i]+nums[j]+nums[left]+nums[right] < target){
left++;
}else{
res.push_back(vector<int> {nums[i],nums[j],nums[left],nums[right]});
while(left < right && nums[left] == nums[left+1]){
left++;
}
while(left < right && nums[right] == nums[right-1]){
right--;
}
left++;
right--;
}
}
}
}
return res;
}
};
1.运用双指针,两次修枝即可
2.四数和可能会溢出,要用一个(long)
344. Reverse String
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0, right = s.size()-1;
while(left < right){
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
}
};
541. Reverse String II
class Solution {
public:
string reverseStr(string s, int k) {
for(int i=0; i<s.size();i = i+2*k){
if(i+k<=s.size()){
reverse(s.begin()+i, s.begin()+i+k);
}else{
reverse(s.begin()+i, s.end());
}
}
return s;
}
};
要注意会出现不够k个的情况