基础知识

数据结构初始化

// 链表节点定义
public class ListNode {
// 结点的值
int val; // 下一个结点
ListNode next; // 节点的构造函数(无参)
public ListNode() {
} // 节点的构造函数(有一个参数)
public ListNode(int val) {
this.val = val;
} // 节点的构造函数(有两个参数)
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
} // 单链表定义
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {
//size存储链表元素的个数
int size;
//虚拟头结点
ListNode head; //初始化链表
public MyLinkedList() {
size = 0;
head = new ListNode(-1);
}
} // 双链表定义
class ListNode{
int val;
ListNode next,prev;
ListNode() {};
ListNode(int val){
this.val = val;
}
} class MyLinkedList { //记录链表中元素的数量
int size;
//记录链表的虚拟头结点和尾结点
ListNode head,tail; public MyLinkedList() {
//初始化操作
this.size = 0;
this.head = new ListNode(-1);
this.tail = new ListNode(-2);
//这一步非常关键,否则在加入头结点的操作中会出现null.next的错误!!!
head.next=tail;
tail.prev=head;
}
}

LeetCode 203

分析1.0

删除链表节点,①考虑空表特殊情况直接返回 ②ans为新链表头节点,第一个val不满足的节点即为头节点 ③删除节点过程, 相等删除节点,不等则p指针后移

/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
// 特殊情况
if(head == null){
return head;
}
// 构建虚拟头结点
int cnt = 1;
ListNode ans = new ListNode(-1), p = new ListNode();
p.next = head;
while(p.next != null){
if(p.next.val == val){
p.next = p.next.next;
continue;
}
if(p.next.val != val){
if(cnt == 1){
ans = p.next;
cnt = 0;
}
p = p.next;
}
}
return ans.val==-1 ? null : ans;
}
}

分析2.0

上面的分析只使用了一个p指针,而新的头结点是计算出来的,并不是统一计算而来。

改进:

设置cur、pre指针,设置虚拟头结点virtualHead

相等时删除 不等时后移

收获:① 使用多个指针简化思维难度 ②新建节点时可以直接将head作为参数传进去

ListNode virtualHead = new ListNode(-1, head);
ListNode pre = virtualHead;
ListNode cur = head;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return virtualHead.next;

LeetCode 707

分析1.0

乍一看有点懵,题目给出的条件有点少,光给个构造器,其他怎么啥也没有,属性呢???我链表的头结点咋办呢???要我自己定义节点吗???

我用内部类定义了Node节点,出了点问题,mark一下:

内部类 

待总结!!! 留个坑

delete报错

public void deleteAtIndex(int index) {
ListNode pre = new ListNode(-1);
ListNode p = head;
pre.next = p;
int cnt = 1;
if(index > 0 && index <= size)
while(cnt <= index){
pre = p;
p = p.next;
pre.next = p;
cnt++;
}// 考虑只有一个元素,要删除第一个元素的特殊情况 用虚拟节点
System.out.println("cnt:" + cnt);
System.out.println("p指针:" + p.val);
log();
pre.next = p.next;
p = pre.next;
this.size--;
}

分析2.0

看了解析,意识到LinkeList的属性应该设置哪些

难点 delete

public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size--;
if (index == 0) {
head = head.next;
return;
}
ListNode pred = head;
for (int i = 0; i < index ; i++) {
pred = pred.next;
}
pred.next = pred.next.next;
}

LeetCode 206

分析1.0

反转链表,第一个节点和最后一个节点互换位置,第二个节点和倒数第二个节点互换位置 ...  一共n个元素 则互换 n/2 次 ,这是二分的思路

class Solution {
public ListNode reverseList(ListNode head) {
// 指定虚拟头结点
ListNode p = new ListNode(-1,head);
int num = 0;
while(p.next != null){
p.next = p.next.next;
num++;
}
// 打印信息 判断p位置
System.out.println(num);
System.out.println(p.val);
for(int i = 0; i<= num/2; i++){
}
return head;
}
}

失误 

从后往前的节点该怎么遍历呢?虽然可以用计数器确定循环终止条件,但是链表和数组不一样,不能实现随机访问

注意 ①将思路变为代码的过程极为重要,在写之前就要弄清楚关键步骤的代码如何实现

分析2.0

灵光一现,可以遍历的时候采用尾插法将节点添加到末尾 qiao

class Solution {
public ListNode reverseList(ListNode head) {
if(head == null){
return head;
}
// 指定虚拟头结点
ListNode ret = new ListNode(-1);
// 遍历指针
ListNode p = head,temp;
while(p != null){
temp = p.next;
p.next = ret.next;
ret.next = p;
//System.out.println(p.val);
p = temp;
}
return ret.next;
}
}

这题没这么复杂,一开始就不要想偏,误入歧途真的很难顶

注意

① 画图分析节点的插入过程 ② 节点next指向新节点后就不是原来的那个节点了

分析3.0

我的思路被头结点局限住了,头结点是可以变化的,指针反向,新的头结点就是原来的最后一个节点 o(╥﹏╥)o

总结

  1. 题目空间复杂度要求不高就造内存
  2. 解题思路关键步骤的代码如何实现要在敲代码前明确 解题思路关键步骤的代码如何实现要在敲代码前明确 解题思路关键步骤的代码如何实现要在敲代码前明确
  3. 链表节点操作模拟要画图
  4. 自定义一个数据类型,如链表等,要考虑属性 元素个数 、构造器
  5. 链表删除 虚拟头结点next指针指向原链表 pre + p 双指针删除 特别是配合索引删除 p移动 pre也要移动
  6. 如何使用计数器实现定位

常用变量名增量更新

size、val、ans、cnt

 
 
 

代码随想录算法训练营day03 | LeetCode 203/707/206的更多相关文章

  1. 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II

    [算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...

  2. 【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和

    [算法训练营day7]LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和 LeetCode454. 四数相加I ...

  3. 【算法训练营day1】LeetCode704. 二分查找 LeetCode27. 移除元素

    [算法训练营day1]LeetCode704. 二分查找 LeetCode27. 移除元素 LeetCode704. 二分查找 题目链接:704. 二分查找 初次尝试 看到题目标题是二分查找,所以尝试 ...

  4. 【算法训练营day8】LeetCode344. 反转字符串 LeetCode541. 反转字符串II 剑指Offer05. 替换空格 LeetCode151. 翻转字符串里的单词 剑指Offer58-II. 左旋转字符串

    [算法训练营day8]LeetCode344. 反转字符串 LeetCode541. 反转字符串II 剑指Offer05. 替换空格 LeetCode151. 翻转字符串里的单词 剑指Offer58- ...

  5. 【算法题 14 LeetCode 147 链表的插入排序】

    算法题 14 LeetCode 147 链表的插入排序: 解题代码: # Definition for singly-linked list. # class ListNode(object): # ...

  6. 代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素

    第一题150. 逆波兰表达式求值 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 注意 两个整数之间的除法只保留整数部分. ...

  7. 代码随想录第八天 |344.反转字符串 、541. 反转字符串II、剑指Offer 05.替换空格 、151.翻转字符串里的单词 、剑指Offer58-II.左旋转字符串

    第一题344.反转字符串 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 s 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的额外空间解决这 ...

  8. Leetcode题解 - 链表简单部分题目代码+思路(21、83、203、206、24、19、876)

  9. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

  10. 程序员进阶之算法练习:LeetCode专场

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由落影发表 前言 LeetCode上的题目是大公司面试常见的算法题,今天的目标是拿下5道算法题: 题目1是基于链表的大数加法,既考察基本 ...

随机推荐

  1. C#不提升自己程序的权限实现操作注册表

    1. 绪论 当我们编写了自己的C#程序,有程序自定义的文件类型时,通常希望它满足以下需求: 双击自定义文件打开自定义程序 自定义文件有着自己的图标 此时,在网上检索可以发现,大多数回答是使用Micro ...

  2. 如何使用Java获取货币符号?

    1. 前言 最近做了一个支付相关的需求,要求在收银台页面显示商品的价格时带上货币符号¥,类似下图中的格式: 最初我是用的下面这样的代码: System.out.println(Currency.get ...

  3. ATM+购物车(思路流程)

    ATM +购物车(思路流程) 启动文件 首先,创建一个start.py作为整个项目启动的启动文件 然后导入os和sys模块,从core中导入src,也就是展示给用户看的 在src.py用户视图层中,先 ...

  4. PyTorch复现VGG学习笔记

    PyTorch复现ResNet学习笔记 一篇简单的学习笔记,实现五类花分类,这里只介绍复现的一些细节 如果想了解更多有关网络的细节,请去看论文<VERY DEEP CONVOLUTIONAL N ...

  5. Spring之Bean注入Spring容器中的方式

    向spring容器中加入bean有以下方式: 通过<Bean>标签 @Configuration + @Bean @Component + 组件扫描 @Import导入[见 Spring注 ...

  6. 旧酒换新瓶,新版M1/M2芯片Macos(Ventura)安装古早版本Python2.7(Python2.x)

    向下兼容特性是软件开发系统的一个重要指标,它是指一个新的系统或者软件能够与旧的系统或软件兼容并正常运行.这意味着旧系统或软件可以在新系统或软件中使用,而不会出现问题.向下兼容对于提高软件或系统的可用性 ...

  7. 《深度探索C++对象模型》第四章 Function语意学

    member function相对于nonmember function之间不存在效率之间的差别,因为编译器内部已经将"member 函数实体"转化为对等的"nonmem ...

  8. ClickHouse(11)ClickHouse合并树MergeTree家族表引擎之SummingMergeTree详细解析

    目录 建表语法 数据处理 汇总的通用规则 AggregateFunction 列中的汇总 嵌套结构数据的处理 资料分享 参考文章 SummingMergeTree引擎继承自MergeTree.区别在于 ...

  9. 狂神——SpringSecurity入门例子(设置不同用户访问权限)

    文章目录 简介 SpringSecurity环境搭建 实现界面的路由跳转 效果 用户认证和授权 授权 认证 效果 注销及权限控制 注销 权限控制 记住我及首页定制 参考资料 简介 狂神的Springb ...

  10. IO多路复用完全解析

    上一篇文章以近乎啰嗦的方式详细描述了BIO与非阻塞IO的各种细节.如果各位还没有读过这篇文章,强烈建议先阅读一下,然后再来看本篇,因为逻辑关系是层层递进的. 1. 多路复用的诞生 非阻塞IO使用一个线 ...