LeetCode 136 只出现一次的数字 简单
一次异或就得出结果
class Solution {
public:
int singleNumber(vector<int>& nums) {
int n=nums.size();
int x=0;
for(int i=0;i<n;i++){
x^=nums[i];
}
return x;
}
};
LeetCode 141 环形链表 简单
用快慢指针就可以了,注意对空指针的处理
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast=head;
ListNode* slow=head;
while(fast!=nullptr){
fast=fast->next;
if(fast!=nullptr){
fast=fast->next;
}
if(fast==slow) return true;
slow=slow->next;
}
return false;
}
};
LeetCode 155 最小栈 简单
用栈实现栈也是让人没想到的
自己写的
class MinStack {
stack<int> stk;
stack<int> min_stk;
public:
/** initialize your data structure here. */
MinStack() {
min_stk.push(INT_MAX);
}
void push(int x) {
stk.push(x);
if(x<min_stk.top()){
min_stk.push(x);
}
else{
int p=min_stk.top();
min_stk.pop();
min_stk.push(x);
min_stk.push(p);
}
}
void pop() {
int p=stk.top();
stk.pop();
int count=0;
while(p!=min_stk.top()){
stk.push(min_stk.top());
min_stk.pop();
count++;
}
min_stk.pop();
while(count>0){
min_stk.push(stk.top());
stk.pop();
count--;
}
}
int top() {
return stk.top();
}
int getMin() {
return min_stk.top();
}
};
题解
class MinStack {
stack<int> x_stack;
stack<int> min_stack;
public:
MinStack() {
min_stack.push(INT_MAX);
}
void push(int x) {
x_stack.push(x);
min_stack.push(min(min_stack.top(), x));
}
void pop() {
x_stack.pop();
min_stack.pop();
}
int top() {
return x_stack.top();
}
int getMin() {
return min_stack.top();
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/min-stack/solution/zui-xiao-zhan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
把栈最小值和当前值组对保存。
class MinStack {
stack<pair<int,int>> stk;
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
if(stk.size()==0) stk.push({x,x});
else stk.push({x,min(x,stk.top().second)});
}
void pop() {
stk.pop();
}
int top() {
return stk.top().first;
}
int getMin() {
return stk.top().second;
}
};
160 相交链表 简单
1.哈希表查找
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*> s;
while(headA!=nullptr){
s.insert(headA);
headA=headA->next;
}
while(headB!=nullptr){
if(s.find(headB)!=s.end()){
return headB;
}
headB=headB->next;
}
return nullptr;
}
};
2.双指针法,pA遍历完指向另一列的头,pB同样操作,直到相遇。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *a = headA, *b = headB;
while(a != b)
{
if(a==nullptr){
a=headB;
}
else{
a=a->next;
}
if(b==nullptr){
b=headA;
}
else{
b=b->next;
}
}
return a;
}
};
169 多数元素 简单
1.用map记录元素出现的次数,在遍历map找出现最多的数
class Solution {
public:
int majorityElement(vector<int>& nums) {
map<int,int> mp;
int res;
for(auto &n:nums){
mp[n]++;
if(mp[n]>nums.size()/2){
res=n;
break;
}
}
return res;
}
};
- 排序,找第n/2个元素
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n=nums.size();
sort(nums.begin(),nums.end());
return nums[n/2];
}
};
方法五:Boyer-Moore 投票算法
思路
如果我们把众数记为 +1+1,把其他数记为 -1−1,将它们全部加起来,显然和大于 0,从结果本身我们可以看出众数比其他数多。
算法
Boyer-Moore 算法的本质和方法四中的分治十分类似。我们首先给出 Boyer-Moore 算法的详细步骤:
我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:
如果 x 与 candidate 相等,那么计数器 count 的值增加 1;
如果 x 与 candidate 不等,那么计数器 count 的值减少 1。
在遍历完成后,candidate 即为整个数组的众数。
我们举一个具体的例子,例如下面的这个数组:
[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
在遍历到数组中的第一个元素以及每个在 | 之后的元素时,candidate 都会因为 count 的值变为 0 而发生改变。最后一次 candidate 的值从 5 变为 7,也就是这个数组中的众数。
Boyer-Moore 算法的正确性较难证明,这里给出一种较为详细的用例子辅助证明的思路,供读者参考:
首先我们根据算法步骤中对 count 的定义,可以发现:在对整个数组进行遍历的过程中,count 的值一定非负。这是因为如果 count 的值为 0,那么在这一轮遍历的开始时刻,我们会将 x 的值赋予 candidate 并在接下来的一步中将 count 的值增加 1。因此 count 的值在遍历的过程中一直保持非负。
那么 count 本身除了计数器之外,还有什么更深层次的意义呢?我们还是以数组
[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
作为例子,首先写下它在每一步遍历时 candidate 和 count 的值:
nums: [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
candidate: 7 7 7 7 7 7 5 5 5 5 5 5 7 7 7 7
count: 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4
我们再定义一个变量 value,它和真正的众数 maj 绑定。在每一步遍历时,如果当前的数 x 和 maj 相等,那么 value 的值加 1,否则减 1。value 的实际意义即为:到当前的这一步遍历为止,众数出现的次数比非众数多出了多少次。我们将 value 的值也写在下方:
nums: [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
value: 1 2 1 2 1 0 -1 0 -1 -2 -1 0 1 2 3 4
有没有发现什么?我们将 count 和 value 放在一起:
nums: [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
count: 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4
value: 1 2 1 2 1 0 -1 0 -1 -2 -1 0 1 2 3 4
发现在每一步遍历中,count 和 value 要么相等,要么互为相反数!并且在候选众数 candidate 就是 maj 时,它们相等,candidate 是其它的数时,它们互为相反数!
为什么会有这么奇妙的性质呢?这并不难证明:我们将候选众数 candidate 保持不变的连续的遍历称为「一段」。在同一段中,count 的值是根据 candidate == x 的判断进行加减的。那么如果 candidate 恰好为 maj,那么在这一段中,count 和 value 的变化是同步的;如果 candidate 不为 maj,那么在这一段中 count 和 value 的变化是相反的。因此就有了这样一个奇妙的性质。
这样以来,由于:
我们证明了 count 的值一直为非负,在最后一步遍历结束后也是如此;
由于 value 的值与真正的众数 maj 绑定,并且它表示「众数出现的次数比非众数多出了多少次」,那么在最后一步遍历结束后,value 的值为正数;
在最后一步遍历结束后,count 非负,value 为正数,所以它们不可能互为相反数,只可能相等,即 count == value。因此在最后「一段」中,count 的 value 的变化是同步的,也就是说,candidate 中存储的候选众数就是真正的众数 maj。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate = -1;
int count = 0;
for (int num : nums) {
if (num == candidate)
++count;
else if (--count < 0) {
candidate = num;
count = 1;
}
}
return candidate;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 反转链表 简单
迭代
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr) return nullptr;
if(head->next==nullptr) return head;
ListNode* pre=nullptr;
ListNode* cur=head;
ListNode* next=head->next;
while(next!=nullptr){
cur->next=pre;
pre=cur;
cur=next;
next=next->next;
}
cur->next=pre;
return cur;
}
};
递归
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr) return nullptr;
if(head->next==nullptr) return head;
ListNode* newHead=reverseList(head->next);
head->next->next=head;
head->next=nullptr;
return newHead;
}
};