一、参考资料
链表理论基础
文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
移除链表元素
题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html
设计链表
题目链接/文章讲解/视频讲解:https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html
反转链表
题目链接/文章讲解/视频讲解:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html
二、LeetCode203.移除链表元素
我的代码
- class Solution {
- public:
- vector<int> sortedSquares(vector<int>& nums) {
- vector<int> res;
-
- for (int i = 0; i < nums.size(); i++){
- nums[i] = nums[i] * nums[i];
- }
- sort(nums.begin(), nums.end());
- return nums;
- }
- };
接下来学习一下双指针的代码实现:
双指针实现
- class Solution {
- public:
- vector<int> sortedSquares(vector<int>& nums) {
- // 这里定义一个结果集,长度为原数组的大小
- vector<int> res(nums.size(), 0);
- // 定义首尾指针
- int firstp = 0;
- int lastp = nums.size() - 1;
- int k = lastp; // k表示结果集的指针,从后向前写入vector
-
- while (firstp <= lastp){
- if (nums[firstp] * nums[firstp] < nums[lastp] * nums[lastp]){
- res[k--] = nums[lastp] * nums[lastp];
- lastp--;
- }
- else{
- res[k--] = nums[firstp] * nums[firstp];
- firstp++;
- }
- }
-
- return res;
- }
- };
三、LeetCode707.设计链表
- class MyLinkedList {
- public:
- // 定义链表节点结构体——单链表
- struct LinkedNode {
- int val; // 节点上存储的元素
- LinkedNode *next; // 指向下一个节点的指针
- LinkedNode(int x) : val(x), next(NULL){} //节点的构造函数
- };
-
- // 初始化链表
- MyLinkedList() {
- _dummyHead = new LinkedNode(0); // 定义虚拟头结点,不是真正的链表头结点
- _size = 0;
- }
-
- // 获取第index个节点的数值,如果index是非法数值直接返回-1
- int get(int index) {
- if (index > (_size - 1) || index < 0) {
- return -1;
- }
- LinkedNode *cur = _dummyHead->next;
- // 如果--index就会陷入死循环
- while (index--) {
- cur = cur->next;
- }
- return cur->val;
- }
-
- // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
- void addAtHead(int val) {
- LinkedNode *newNode = new LinkedNode(val);
- newNode->next = _dummyHead->next;
- _dummyHead->next = newNode;
- _size++;
- }
- // 在链表最后面添加一个节点
- void addAtTail(int val) {
- LinkedNode *newNode = new LinkedNode(val);
- LinkedNode *cur = _dummyHead;
- while(cur->next != NULL) {
- cur = cur->next;
- }
- cur->next = newNode;
- _size++;
- }
-
- // 添加节点
- void addAtIndex(int index, int val) {
- if (index > _size) return;
- if (index < 0) index = 0;
- LinkedNode *newNode = new LinkedNode(val);
- LinkedNode *cur = _dummyHead;
- while (index--) {
- cur = cur->next;
- }
- newNode->next = cur->next;
- cur->next = newNode;
- _size++;
- }
-
- // 删除节点
- void deleteAtIndex(int index) {
- if (index >= _size || index < 0) {
- return;
- }
- LinkedNode *cur = _dummyHead;
- while (index--) {
- cur = cur->next;
- }
- LinkedNode *tmp = cur->next;
- cur->next = tmp->next; // cur->next = cur->next->next;
- delete tmp;
- _size--;
- }
- private:
- int _size;
- LinkedNode* _dummyHead;
- };
-
- // // 打印链表
- // void printLinkedList() {
- // LinkedNode* cur = _dummyHead;
- // while (cur->next != nullptr) {
- // cout << cur->next->val << " ";
- // cur = cur->next;
- // }
- // cout << endl;
- // }
-
-
-
- /**
- * Your MyLinkedList object will be instantiated and called as such:
- * MyLinkedList* obj = new MyLinkedList();
- * int param_1 = obj->get(index);
- * obj->addAtHead(val);
- * obj->addAtTail(val);
- * obj->addAtIndex(index,val);
- * obj->deleteAtIndex(index);
- */
四、LeetCode206.反转链表
这个题以前是做过的,链表用的不熟练还是不能很快写出来(这篇先写了双指针法,递归法下次补上)
双指针法实现反转链表
- class Solution {
- public:
- ListNode* reverseList(ListNode* head) {
- ListNode* temp; // 保存cur的下一个节点
- ListNode* cur = head;
- ListNode* pre = NULL;
- while(cur) {
- temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
- cur->next = pre; // 翻转操作
- // 更新pre 和 cur指针
- pre = cur;
- cur = temp;
- }
- return pre;
- }
- };
递归法(卡哥带注释版本)
- class Solution {
- public:
- ListNode* reverseList(ListNode* head) {
- // 边缘条件判断
- if(head == NULL) return NULL;
- if (head->next == NULL) return head;
-
- // 递归调用,翻转第二个节点开始往后的链表
- ListNode *last = reverseList(head->next);
- // 翻转头节点与第二个节点的指向
- head->next->next = head;
- // 此时的 head 节点为尾节点,next 需要指向 NULL
- head->next = NULL;
- return last;
- }
- };
Day03总结:
指针操作的原理还是可以理解的,但是写代码就不太顺手
看代码能看懂,但自己写的时候容易遗忘,或者思路容易不清楚
规范化操作很重要,包括对节点空间的释放(Java和python不需要考虑)以及结构体的初始化等。