移动零
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int ptr1 = 0,ptr2 = 1;
if(nums.size()<=1){
return;
}
while(ptr2<nums.size()){
while(nums[ptr2]==0){ //是0则右移到非0位置,但不能超过边界
if(ptr2>=nums.size()-1)
break;
ptr2++;
}
if(nums[ptr1]==0&&nums[ptr2]!=0){ //是0则交换
nums[ptr1] = nums[ptr2];
nums[ptr2] = 0;
}
ptr1++;
if(ptr1>=ptr2) //ptr1超过ptr2唯一的情况就是前面全是非0数
ptr2 = ptr1 + 1;
}
}
};
虽然写得很烂,但是是4ms,逻辑也算很清晰了。
链表
链表就是每个节点的存储都是动态决定的,而且每个节点都有一个指向下一个节点的指针,由于存储是动态非连续的,因此我们在插入删除节点时能取到O(1)的优秀效果。
链表必备要素:节点,指针(可以有两个,即双向链表)
一些重要的点:
检查成环:使用快慢指针
两个链表的第一个交点:从尾到头搜索即可找到分歧点
下面是翻转链表,挺简单的,但是一定要注意好指向
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL)
return NULL;
ListNode* myhead = head->next; //直接从第二跳开始,避免死循环
ListNode* temp = head; //永远指向前一跳,原先的head位置永远都是前一跳!!!
while(myhead!=NULL){
temp->next = myhead->next; //前一跳直接指向下一跳
myhead-> next = head; //将该节点放在头部
head = myhead; //头部变换地址
myhead = temp->next; //换成之前的下一跳
}
return head;
}
};
下面是旋转链表的代码,关键在于切割:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(head==NULL||k==0||head->next==NULL)
return head;
int size = 1;//链表长度
ListNode* end = head;//倒数
while(end->next!=NULL){
size+=1;
end=end->next;
}
k = size-k%size; //确认切割位点在第几位
ListNode* end_k = head;//倒数第k
int i = 0;
while(++i<k)
end_k = end_k->next;
end->next = head;
head = end_k->next;
end_k->next = NULL;
return head;
}
};
HASH
hash是一种映射关系,我们可以通过hash将大范围的数据缩在制定范围的桶里,还可以把内容映射成键值,在O(1)时间内找到目标。简单来说,visit数组就是最简单的一对一的hash映射。
class MyHashSet {
private:
bool a[1000100];
public:
/** Initialize your data structure here. */
MyHashSet() {
for(int i=0;i<1000100;i++)
a[i] = false;
}
void add(int key) {
a[key] = true;
}
void remove(int key) {
a[key] = false;
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
return a[key];
}
};
上面是最简单的,但是实际情况中不会这么用。。。。
总结
c++ hash库调用方法:
unordered_set<int> hashset;
hashset.insert(2);
hashset.erase(2);
hashset.count(2)
vector清空方法 vector<int>().swap(nums);