删除链表中的节点
要点:node.val = node.next.val
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}
}
删除链表的倒数第 N 个结点
要点:
方法1:记录length,然后减掉n,找到n的前一个节点,不用dummy的话,就特判一下头节点
java
/**
* 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 removeNthFromEnd(ListNode head, int n) {
//记录长度
ListNode temp1 = head;
int length = 0;
while(temp1 != null){
length++;
temp1 = temp1.next;
}
int target = length - n;
if(target == 0){
return head.next;
}
ListNode dummy = new ListNode(-1, head);
ListNode temp2 = dummy.next;
for(int i = 1; i < target; i++){
temp2 = temp2.next;
}
temp2.next = temp2.next.next;
return dummy.next;
}
}
方法2:dummy。left。right,right先走n,然后right到last的时候,left在倒数n+1节点上
java
/**
* 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 removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0,head);
ListNode left = dummy;
ListNode right = dummy;
while(n-- > 0){
right = right .next;
}
while(right.next != null){
right = right.next;
left = left.next;
}
left.next = left.next.next;
return dummy.next;
}
}
删除排序链表中的重复元素
要点:cur,然后对比cur.next
java
/**
* 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 deleteDuplicates(ListNode head) {
if(head == null){
return head;
}
ListNode cur = head;
while(cur.next != null){
if(cur.next.val == cur.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return head;
}
}
删除排序链表中的重复元素 II
要点:需要dummy,cur.next 和cur.next,next
java
/**
* 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 deleteDuplicates(ListNode head) {
//需要哨兵节点,因可能删除头节点
ListNode dummy = new ListNode(-1, head);
ListNode cur = dummy;
while(cur.next != null && cur.next.next != null){
int val = cur.next.val;
if(cur.next.next != null && cur.next.next.val == val){
while(cur.next != null && cur.next.val == val){
cur.next = cur.next.next;
}
}else{
cur = cur.next;
}
}
return dummy.next;
}
}
随机知识
JVM内存模型-JVM 运行时数据区有哪些?各自放什么?
候选人 :
好的,JVM 运行时数据区是 Java 程序运行的内存基础,一共分为五个核心区域。我按线程共享 和线程私有分成两类来说。
先总览整体架构
线程共享的有两块:堆 和方法区 。线程私有的有三块:虚拟机栈 、本地方法栈 、程序计数器。
线程私有的意思是每个线程都有一份独立的内存空间,线程结束自动释放,互不干扰。线程共享的意思是所有线程都能访问同一块内存,这也是多线程并发问题产生的根源。
逐一详解五个区域
第一,堆。 堆是 JVM 内存中最大的一块,所有通过 new 创建出来的对象和数组都分配在堆上。它是垃圾回收器重点管理的区域,所以也叫做"GC 堆"。堆里保存的是每个对象的实例数据,比如一个 Person 对象里 name 和 age 的具体值。堆是线程共享的,所有线程都可以访问堆里的对象。因为堆里对象生命周期复杂,有朝生夕死的,也有长期存活的,所以现在 JVM 把堆逻辑上分成年轻代和老年代,分别用不同的垃圾回收策略处理。
第二,方法区。 方法区存放的是类的元信息,也就是类被加载后 JVM 需要记录的结构性数据,包括类的版本、字段、方法、接口、静态变量、常量池,还有即时编译器编译后的代码缓存。它也是线程共享的。JDK7 及之前,方法区的实现在堆里,叫永久代,大小固定,容易 OOM。JDK8 开始,方法区的实现移到了本地内存里,改叫元空间,大小默认不限制,只受物理内存限制,更灵活,也减少了堆的 GC 压力。经常聊的"运行时常量池"也在方法区里,字符串常量池在 JDK7 时被移到了堆里,因为堆比永久代空间大,GC 更积极,可以减少 OOM。
第三,虚拟机栈。 每个线程启动时,JVM 会给它分配一个独立的虚拟机栈。栈里存的不是对象,而是一个一个的栈帧。每调用一个方法,就创建一个栈帧压入栈顶,方法执行完,栈帧弹出。栈帧里主要存三类数据:一是局部变量表,存放方法内部定义的局部变量,包括基本类型的值和对象的引用(对象本身在堆里,栈里只存指向堆的指针);二是操作数栈,JVM 执行字节码指令时用于计算的中间数据暂存区域;三是返回值等信息。栈内存由 JVM 自动管理,方法结束栈帧弹出,内存就释放了。如果方法递归调用次数过多,栈帧撑满整个栈,就会抛出 StackOverflowError。
第四,本地方法栈。 它和虚拟机栈结构类似,但服务对象不同。虚拟机栈为 Java 方法服务,本地方法栈为 Native 方法服务,也就是 Java 调用底层 C/C++ 写的操作系统接口时使用。比如 Thread.start() 底层创建操作系统线程,就会用到本地方法栈。
第五,程序计数器。 它是五块内存中最小的,每个线程都有一个独立的程序计数器。它只记录一个信息:当前线程正在执行的字节码指令的行号。CPU 在多线程间来回切换执行,每次切回来的时候,线程必须知道"上一轮我执行到哪一行了",这就是程序计数器的意义。这个区域是 JVM 规范中唯一没有规定任何 OutOfMemoryError 的区域。
用一句代码把五个区域串起来
拿 String s = new String("hello") 这句代码来说:
s这个引用变量在虚拟机栈的局部变量表里。new String("hello")这个对象实例分配在堆里。String这个类的元信息(类名、有哪些方法、字段)存放在方法区里。- 执行这行代码时,当前线程执行到第几行由程序计数器记录。
- 如果在 Native 方法中创建对象,本地方法栈会参与进来。
这样就能把五个区域和日常写代码的变量、对象、类信息一一对上。
碎碎念:后续会更新每天学习的八股和算法 题,开始准备秋招的第21天。努力连续更新100天!以后每天就按,秋招项目【java+agent】,科研,必做项目,算法,八股,锻炼身体来总结。
总结:今天效率巨低,还是算法题及时反馈感强,不想学其他的,不行!以后要以程序员为职业,首先就是要热爱代码呀!!!!!加油加油加油
1.算法要系统过一遍【灵神】8/27【晚上】2h
2.秋招项目,【java】开始实际看业务,2.9/10;无
【agent】还在学,决定把helloagent看一遍,5/16;无
3.科研要跑一下,无
4.检测项目也得总结文档,无,
5.训练项目看看先选择好,无,
6.背八股,无
7.锻炼身体,无
反思:昨天玩手机起得太晚,周末一点不想学习,自己规划的太不合理,当你熬夜的时候就应该知道今天完不成任务,安排事情应该要往前看两步,一天真正清醒的时间很少的呀。
这周相当于啥也没干。
第三周总结改进
1:不要熬夜,不要向明天借时间,今天的事情今天就要干完。
2.运动不能停止
3.相信自己,增强对时间的把控力,
4.得每天看点面经还是,保持状态
5.脑子动起来,感觉现在脑子特别笨,看点脑筋急转弯