目录
1.876. 链表的中间结点 - 力扣(LeetCode)
求中间结点的快慢指针做法
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode *slow = head, *fast = head;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
};
当链表长度为奇数时:fast指针指向链表的最后一个结点,即fast->next为空,slow指向中间结点。
当链表长度为偶数是:fast指向链表最后一个结点的下一个结点,即fast为空,slow指向中间两个结点的第二个结点。
2.143. 重排链表 - 力扣(LeetCode)
哎哟脑袋痛脑袋痛
最终的链表就是在原链表的基础上取第一个、倒数第一个、第二个、倒数第二个......
先找到中间结点,然后将中间结点开始的链表反转
完了,又不是很理解了,这是当时对着代码画出来的迭代过程
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
// 找中间结点
ListNode* find_mid(ListNode *head){
ListNode *slow = head;
ListNode *fast = head;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
ListNode* reverse(ListNode *head){
ListNode *pre = nullptr;
ListNode *cur = head;
while(cur){
ListNode *nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
public:
void reorderList(ListNode* head) {
ListNode *mid = find_mid(head);
ListNode *head2 = reverse(mid);
while(head2->next){
ListNode *nxt = head->next;
ListNode *nxt2 = head2->next;
head->next = head2;
head2->next = nxt;
head = nxt;
head2 = nxt2;
}
}
};
3.160. 相交链表 - 力扣(LeetCode)
做过的题,小姐姐你又开始乱七八糟做了
思路基本正确但是又有点不清晰,存在一个错误就是要判断pa、pb 而不是它们的next
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *pa = headA, *pb = headB;
while(pa != pb){
if(!(pa)){
pa = headB;
}
else{
pa = pa->next;
}
if(!(pb)){
pb = headA;
}
else{
pb = pb->next;
}
}
return pb;
}
};
4. 706. 设计哈希映射 - 力扣(LeetCode)
水一道,助助兴
用了一个小技巧+1、-1
为什么要这样呢,因为这样可以区分这个这个键值是否被设置过,如果是0就是没有被设置过的,如果不是0就说明是设置过的有元素的。比如:get方法查询一个键时,由于返回的是map[key]-1,对于已经被删除的键(值为0)会得到0 - 1 = -1,这可以作为一个标志,表明该键不存在或者已经被删除。
如果不+1,那么存储0的时候就无法判断是设置过的还是没被设置过的,-1是因为存储的时候+1了要还原。
class MyHashMap {
private:
int map[1000010] = {0};
public:
MyHashMap() {
}
void put(int key, int value) {
map[key] = value + 1;
}
int get(int key) {
return map[key] - 1;
}
void remove(int key) {
map[key] = 0;
}
};
5.217. 存在重复元素 - 力扣(LeetCode)
农村就这生活,简简单单一顿四个菜。
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
unordered_set<int> s;
for(int i = 0; i < nums.size(); i++){
if(s.find(nums[i]) != s.end()){
return true;
}
s.insert(nums[i]);
}
return false;
}
};
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size()-1; i++){
if(nums[i] == nums[i+1])
return true;
}
return false;
}
};
6.128. 最长连续序列 - 力扣(LeetCode)
我觉得这个题目其实还挺有意思的。
首先我自己乱作一通没做出来。
这个题目的思路是这样的:首先去重,把这个数组的所有元素放到一个set里面。然后判断每个数字会不会是可能的连续序列的起点。怎么判断呢:如果在这个set中这个数字num存在num-1,那么这个数字就是连续序列的起点。然后就开始计算连续序列的长度啊。
为什么不根据是否存在num+1来判断这个数字num是不是一个连续序列的起点呢。因为这样子我们可以确保是从这个连续序列的最小值开始计算的并且不会重复计算。比如1,2,3,4,5,6 我们从1开始计算完了,就不用再从2开始再计算一遍。没有意义。
class Solution {
public:
int longestConsecutive(vector<int> &nums) {
unordered_set<int> s;
for(const int& num : s){
if(s.find(num-1) == s.end()){
int curNum = num;
int len = 1;
while(s.find(curNum+1) != s.end()){
curNum += 1;
len += 1;
}
count = max(count, len);
}
}
}
return count;
}
}: