本文的网课内容学习自B站左程云老师的算法详解课程,旨在对其中的知识进行整理和分享~
一.值传递和引用传递
分类
- 基本数据类型:当传递基本数据类型(如int、double、char等)时,传递的是实际值的副本。在方法内部对参数的修改不会影响到原始值。
- 引用数据类型:当传递引用数据类型(如对象、数组等)时,传递的是对象的引用的副本。虽然在方法内部可以通过引用来修改对象的属性,但无法改变原始引用本身。
代码实现
package listreverse;
public class Transmit {
public static void main(String[] args) {
// int、long、byte、short
// char、float、double、boolean
// 还有String
// 都是按值传递
int a = 10;
f(a);
System.out.println(a);
// 其他类型按引用传递
// 比如下面的Number是自定义的类
Number b = new Number(5);//在堆区开辟一个空间存放5,定义一个b指向存放5的地址
g1(b);//拷贝一个b',也指向5的地址,这行代码的目的是将b'指向null,但b仍然指向5
System.out.println(b.val);
g2(b);//同样拷贝一个b',将b'指向空间的值改成6,但b和b'指向的空间是1个,所以b的值也变了
System.out.println(b.val);
// 比如下面的一维数组
int[] c = {1, 2, 3, 4};
g3(c);
System.out.println(c[0]);
g4(c);
System.out.println(c[0]);
}
public static void f(int a) {
a = 0;
}
public static class Number {
public int val;
public Number(int v) {
val = v;
}
}
public static void g1(Number b) {
b = null;
}
public static void g2(Number b) {
b.val = 6;
}
public static void g3(int[] c) {
c = null;
}
public static void g4(int[] c) {
c[0] = 100;
}
}
二.单链表反转
题目:反转链表
算法原理
一、总体思路
- 目的:这个算法的目的是将一个单链表进行反转。例如,原始链表为1 -> 2 -> 3,经过反转后变为3 -> 2 -> 1。
- 采用的方法:采用迭代的方式,通过不断调整链表节点之间的指针方向来实现反转。
二、具体实现步骤
1.初始化指针
- 定义了三个指针:
pre
(初始化为null
),head
(初始化为链表的头节点)和next
(初始化为null
)。 pre
指针用于记录已经反转部分的链表的尾节点(初始时因为还没有反转任何节点,所以为null
)。next
指针用于临时保存head
节点的下一个节点,防止在调整指针时丢失链表后续的节点。
2.迭代过程
- 在
while (head!= null)
循环中:- 首先,
next = head.next;
这一步是保存head
节点的下一个节点,因为接下来要改变head
节点的next
指针指向。 - 然后,
head.next = pre;
这是关键的一步,将head
节点的next
指针指向已经反转部分的链表的尾节点(开始时为null
),这样就实现了将当前head
节点从原链表中“切断”并连接到反转后的链表上。 - 接着,
pre = head;
更新pre
指针,将pre
指向当前已经处理好(反转)的节点,也就是head
节点。 - 最后,
head = next;
将head
指针移动到原链表中的下一个节点,以便进行下一轮的反转操作。
- 首先,
3.返回结果
- 当
while
循环结束后,head
指针已经遍历到原链表的末尾(变为null
),此时pre
指针指向的就是反转后的链表的头节点,所以返回pre
。
代码实现
// 单链表节点
public static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
// 反转单链表测试链接 : https://leetcode.cn/problems/reverse-linked-list/
class Solution {
public static ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode next = null;
while (head != null) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
}
三.双链表反转
题目:给你双链表的头节点 head
,请你反转链表,并返回反转后的链表。
算法原理
一.总体思路
- 目的是反转一个双链表。双链表与单链表不同,它的每个节点既有指向下一个节点的指针
next
,也有指向前一个节点的指针last
。反转双链表就是要将所有节点的next
和last
指针方向都反转过来。 - 采用迭代的方式,通过逐步调整每个节点的
next
和last
指针来实现整个双链表的反转。
二.具体实现步骤
- 初始化指针
- 定义了两个指针
pre
(初始化为null
)和next
(初始化为null
),以及双链表的头节点head
。这里pre
用于记录已经反转部分的双链表的尾节点(初始时因为还没有反转任何节点,所以为null
),next
用于临时保存head
节点的下一个节点,防止在调整指针时丢失双链表后续的节点。
- 定义了两个指针
- 迭代过程
- 在
while (head!= null)
循环中:- 首先,
next = head.next;
这一步是保存head
节点的下一个节点,因为接下来要改变head
节点的next
指针指向。 - 然后,
head.next = pre;
这是反转双链表中next
指针方向的关键一步,将head
节点的next
指针指向已经反转部分的双链表的尾节点(开始时为null
)。 - 接着,
head.last = next;
这一步是调整head
节点的last
指针,将其指向原双链表中head
节点的下一个节点(即之前保存的next
节点),这样就保证了双链表的双向性在反转过程中得以维持。 - 之后,
pre = head;
更新pre
指针,将pre
指向当前已经处理好(反转)的节点,也就是head
节点。 - 最后,
head = next;
将head
指针移动到原双链表中的下一个节点,以便进行下一轮的反转操作。
- 首先,
- 在
- 返回结果
- 当
while
循环结束后,head
指针已经遍历到原双链表的末尾(变为null
),此时pre
指针指向的就是反转后的双链表的头节点,所以返回pre
。
- 当
代码实现
// 双链表节点
public static class DoubleListNode {
public int value;
public DoubleListNode last;
public DoubleListNode next;
public DoubleListNode(int v) {
value = v;
}
}
// 反转双链表
// 没有找到测试链接
public static DoubleListNode reverseDoubleList(DoubleListNode head) {
DoubleListNode pre = null;
DoubleListNode next = null;
while (head!= null) {
next = head.next;
head.next = pre;
head.last = next;
pre = head;
head = next;
}
return pre;
}