206. 反转链表 - easy
这里只写了迭代,没有递归
//21.24
//21.31
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == nullptr || head->next == nullptr) return head;
ListNode *pre = head, *cur = head->next, *nex = cur->next;
while(cur != nullptr) {
cur->next = pre;
pre = cur;
cur = nex;
if(nex) nex = nex->next;
}
head->next = nullptr; //记得要设置第一个节点的next指向nullptr
return pre;
}
};
136. 只出现一次的数字 - easy
出现两次可以用位运算异或抵消掉(相同为0,不同为1),其实异或可以找出nums中有奇数个x的这个x,前提是其他数字必须出现偶数次。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int tmp = nums[0];
for(int i = 1; i < nums.size(); i++) {
tmp = tmp^nums[i];
}
return tmp;
}
};
169. 多数元素 - easy
方法一:map/unordered_map
//12.50
//12.52
class Solution {
public:
int majorityElement(vector<int>& nums) {
int size = nums.size()/2;
map<int, int> num_cnt; //时间复杂度:map为O(nlogn),unordered_map为O(n)
for(auto x : nums) {
if(++num_cnt[x] > size)
return x;
}
return 0;
}
};
方法二:排序
结论:排序后在index = ⌊n / 2⌋,nums[index]必定是众数。
因为众数数量大于⌊n / 2⌋,无论这个数是在排序后的nums中位于左,右(中间略),必定占据多于⌊n / 2⌋个格子,所以才有此结论
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size()/2];
}
};
方法三:Boyer-Moore投票算法(参考:leetcode答案)
用下图举例,定义candidate, count
- candidate一开始为nums[0], count = 1, 此后若读入一个数等于candidate则count++;若不同则count–,直到count = 0,则candidate等于下一个读入的数字,count重新等于1
(相当于,所有人投票,等于candidate就投赞成,不等于就反对,因为众数数量大于⌊n / 2⌋,所以必定是众数当选) - 这种算法暂时只想到用于求众数
- 这种算法其实很像分治算法(参考:多数投票算法(Boyer-Moore Algorithm)详解)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int cnt = 1, x = nums[0];
for(int i = 1; i < nums.size(); i++) {
if(cnt == 0) {
cnt = 1;
x = nums[i];
continue;
}
if(x == nums[i]) cnt++;
else cnt--;
}
return x;
}
};
338. 比特位计数 - medium
//15.37
//15.43
//这里用动态规划算法,或者可以用位运算(& - 与运算)获得每一位0/1来得到答案
class Solution {
public:
vector<int> countBits(int num) {
vector<int> ans(num+1, 0);
for(int i = 1; i <= num; i++) {
int t = i; //为了避免操作符的优先顺序造成问题,新定义一个t
ans[i] = ans[t >> 1] + i % 2; //这里数字i有多少个1,
//在二进制中由i/2以及i中最有一位(0/1)决定
}
return ans;
}
};