提示:面试时链表解题方法论
1.对于笔试,不用太在乎空间复杂度,一切为了时间复杂度
2.对于面试,时间复杂度依然放在第一位,但是一定要找到空间最省的方法
文章目录
前言
本文主要讲解了几道与链表有关的基础提醒,帮助读者更好的运用链表,对这种数据结构有更好的掌握。
一、快慢指针
- 输入链表头结点,奇数长度返回中点,偶数长度返回上中点。
- 输入链表头结点,奇数长度返回中点,偶数长度返回下中点。
- 输入链表头结点,奇数长度返回中点前一个,偶数长度返回上中点前一个。
- 输入链表头结点,奇数长度返回中点前一个,偶数长度返回下中点前一个。
package LinkedList;
import LinkedList.PatitionList.node;
public class FastAndSlowPointer {
public class node{
node next;
int val;
public node(int val) {
this.val = val;
this.next = null;
}
public node(int val, node next) {
this.val = val;
this.next = next;
}
public String toString() {
String ans = "";
node cur = this;
while(cur != null) {
ans += Integer.toString(cur.val);
cur = cur.next;
}
return ans;
}
}
public int ReturnUpMid(node head) {
if(head == null) return -1;
int ans;
node fast = head;
node slow = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ans = slow.val;
return ans;
}
public int ReturnLowMid(node head) {
if(head == null) return -1;
int ans;
node fast = head;
node slow = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
if(fast.next != null) slow = slow.next; //如果是偶数,慢指针再走一次
ans = slow.val;
return ans;
}
public int ReturnFrontUpMid(node head) {
if(head == null) return -1;
if(head.next == null) return -1;
int ans;
node fast = head;
node slow = head;
if(fast.next != null && fast.next.next != null) { //快指针多走一步(慢指针少走一步)
fast = fast.next.next;
}
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ans = slow.val;
return ans;
}
public int ReturnFrontLowMid(node head) {
if(head == null) return -1;
if(head.next == null) return -1;
int ans;
node fast = head;
node slow = head;
if(fast.next != null && fast.next.next != null) { //快指针多走一步(慢指针少走一步)
fast = fast.next.next;
}
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
if(fast.next != null) slow = slow.next;
ans = slow.val;
return ans;
}
public static void main(String[] args) {
FastAndSlowPointer f = new FastAndSlowPointer();
node head = new FastAndSlowPointer().new node(0);
node one = new FastAndSlowPointer().new node(1);
node two = new FastAndSlowPointer().new node(2);
node three = new FastAndSlowPointer().new node(3);
node four = new FastAndSlowPointer().new node(4);
node five = new FastAndSlowPointer().new node(5);
node six = new FastAndSlowPointer().new node(6);
head.next = one;
one.next = two;
two.next = null;
three.next = four;
four.next = five;
five.next = six;
six.next = null;
System.out.println("奇数原串:" + head);
System.out.println("偶数原串:" + three);
// 0, 1, 2
//3, 4, 5, 6
//返回上中点
System.out.println("返回上中点");
System.out.println("奇数" + f.ReturnUpMid(head));
System.out.println("偶数" + f.ReturnUpMid(three));
//返回下中点
System.out.println("返回下中点");
System.out.println("奇数" + f.ReturnLowMid(head));
System.out.println("偶数" + f.ReturnLowMid(three));
//返回上中点前一个
System.out.println("返回上中点前一个");
System.out.println("奇数" + f.ReturnFrontUpMid(head));
System.out.println("偶数" + f.ReturnFrontUpMid(three));
//返回下中点前一个
System.out.println("返回下中点前一个");
System.out.println("奇数" + f.ReturnFrontLowMid(head));
System.out.println("偶数" + f.ReturnFrontLowMid(three));
}
}
运行结果
二、判断链表回文
共有两种方法,
- 找到中点,之后将前一部分的值存储起来。再倒序与后半部分做对比。时间复杂度O(n) 空间复杂度O(n)
2.找到中点,之后将后一部分链表反转,中点指空,得到两个链表,则两个链表按序对比。对比完成后将链表还原。时间复杂度O(n) 空间复杂度O(1)
package LinkedList;
import java.util.LinkedList;
import java.util.List;
public class JudgementPalindrome {
public class node{
int val;
node next;
public node(int val) {
this.val = val;
this.next = null;
}
public node(int val, node next) {
this.val = this.val;
this.next = next;
}
public node insert(int val) {
node next = new node(val);
node cur = this;
while(cur.next != null) {
cur = cur.next;
}
cur.next = next;
return this;
}
public String toString() {
String ans = "";
node cur = this;
while(cur != null) {
ans += Integer.toString(cur.val);
cur = cur.next;
}
return ans;
}
}
public node[] findUpMid(node head) {
if(head == null) return null;
node slow = head;
node fast = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
if(fast.next != null) {
return new node[] {slow, slow.next};
}
return new node[] {slow, slow};
}
public boolean method1(node head) { //找到中点位置,之后比较相当于将链表对着 时间复杂度O(n) 空间复杂度O(n)
boolean ans = true;
node[] mid = this.findUpMid(head);
if(mid == null) return ans;
// System.out.println("中点:" + mid[0].val + " " + mid[1].val);
node cur = head;
List<Integer> list = new LinkedList<>();
while(cur != mid[0].next) {
list.add(cur.val);
cur = cur.next;
}
cur = mid[1];
int size = list.size();
for(int i = size - 1; i >= 0; --i) {
if(cur == null || cur.val != list.get(i)) {
ans = false;
break;
}
cur = cur.next;
}
return ans;
}
//链表反转
public node reverse(node head) {
if(head == null || head.next == null) return head;
node p1 = head;
node p2 = head.next;
head.next = null; //头变尾
while(p2 != null) {
node next = p2.next;
p2.next = p1;
p1 = p2;
p2 = next;
}
return p1;
}
public boolean method2(node head) { //找到中点位置,然后将后半部分反转,之后遍历两个链表同时进行比较,比较完成后将链表复原 时间复杂度O(n) 空间复杂度O(1)
boolean ans = true;
node[] mid = this.findUpMid(head);
if(mid == null) return ans;
node head2 = reverse(mid[1]);
mid[0].next = null; //拆分
node cur1 = head;
node cur2 = head2;
while(cur1 != null && cur2 != null) {
if(cur1.val != cur2.val) {
ans = false;
break;
}
cur1 = cur1.next;
cur2 = cur2.next;
}
if(cur1 != null || cur2 != null) {
ans = false;
}
//复原链表
head2 = reverse(head2);
if(mid[0] != mid[1]) { //如果两个中点不是同一个需要链接一下
mid[0].next = mid[1];
}
return ans;
}
public static void main(String[] args) {
System.out.println("—————————————————————原串———————————————————————————");
node head1 = new JudgementPalindrome().new node(0);
head1.insert(1).insert(2).insert(3).insert(4).insert(4).insert(3).insert(2).insert(1).insert(0);
System.out.println("head1:" + head1);
node head2 = new JudgementPalindrome().new node(0);
head2.insert(1).insert(2).insert(3).insert(4).insert(3).insert(2).insert(1).insert(0);
System.out.println("head2:" + head2);
node head3 = new JudgementPalindrome().new node(0);
head3.insert(1).insert(2).insert(3).insert(4).insert(3).insert(2).insert(1);
System.out.println("head3:" + head3);
System.out.println("————————————————————————————————————————————————————");
JudgementPalindrome f = new JudgementPalindrome();
System.out.println("方法一");
System.out.println("偶回文串" + f.method1(head1));
System.out.println("奇回文串" + f.method1(head2));
System.out.println("非回文串" + f.method1(head3));
System.out.println("————————————————————————————————————————————————————");
System.out.println("方法二");
System.out.println("偶回文串" + f.method2(head1));
System.out.println("奇回文串" + f.method2(head2));
System.out.println("非回文串" + f.method2(head3));
System.out.println("————————————————————查看链表是否发生改变—————————————————————");
System.out.println("head1:" + head1);
System.out.println("head2:" + head2);
System.out.println("head3:" + head3);
}
}
运行结果
三、将单链表按照某值划分成左边小中间相等右边大的形式
- 放入数组进行partition,之后重新串联
- 六个指针,但要考虑某个区域可能没有值
package LinkedList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class PatitionList {
public class node{
int val;
node next;
public node(int val) {
this.val = val;
this.next = null;
}
public node(int val, node next) {
this.val = this.val;
this.next = next;
}
public node insert(int val) {
node next = new node(val);
node cur = this;
while(cur.next != null) {
cur = cur.next;
}
cur.next = next;
return this;
}
public String toString() {
String ans = "";
node cur = this;
while(cur != null) {
ans += Integer.toString(cur.val);
cur = cur.next;
}
return ans;
}
}
public node method2(node head, int key) { //用六个指针3个链表分别进行计数 时间复杂度O(n) 空间复杂度O(1)
node ans = null;
//小于k的链表
node lh = null;
node le = null;
//等于k的链表
node eh = null;
node ee = null;
//大于k的链表
node mh = null;
node me = null;
node cur = head;
while(cur != null) {
if(cur.val == key) {
if(eh == null) {
eh = cur;
ee = eh;
}else {
ee.next = cur;
ee = ee.next;
}
}else if(cur.val > key) {
if(mh == null) {
mh = cur;
me = mh;
}else {
me.next = cur;
me = me.next;
}
}else {
if(lh == null) {
lh = cur;
le = mh;
}else {
le.next = cur;
le = me.next;
}
}
cur = cur.next;
}
if(le != null) le.next = null;
if(me != null) me.next = null;
if(ee != null) ee.next = null;
if(le != null) {
le.next = eh;
ee = ee != null? ee: le;
}
if(ee != null) {
ee.next = mh;
}
return lh != null? lh: eh != null? eh: mh;
}
public node partition(node head, int key) { //将值存储在数组中,对数组进行partition再重新建立链表 时间复杂度O(n) 空间复杂度O(n)
node ans = null;
List<Integer> list = new LinkedList<>();
node cur = head;
while(cur != null) {
list.add(cur.val);
cur = cur.next;
}
int[] nums = new int[list.size()];
for(int i=0; i<list.size(); ++i) {
nums[i] = list.get(i);
}
partition_help(nums, key);
ans = new node(nums[0]);
cur = ans;
for(int i=1; i<nums.length; ++i) {
cur.next = new node(nums[i]);
cur = cur.next;
}
return ans;
}
public void partition_help(int[] nums, int key) {
if(nums.length <= 1) return ;
int less = 0;
int cur = 0;
int more = nums.length - 1;
while(cur <= more) {
while(nums[cur] > key && cur <= more) {
int temp = nums[more];
nums[more] = nums[cur];
nums[cur] = temp;
--more;
}
if(nums[cur] < key) {
int temp = nums[less];
nums[less] = nums[cur];
nums[cur] = temp;
++less;
}
++cur;
}
}
public static void main(String[] argv) {
PatitionList f = new PatitionList();
node head = new PatitionList().new node(5);
head.insert(5).insert(5);
for(int i=0; i<20; ++i) {
head.insert((int)(Math.random() * 10));
}
System.out.println("原 串:" + head);
System.out.println("方法一排序后:" + f.partition(head, 5));
System.out.println("方法二排序后:" + f.partition(head, 5));
}
}
运行结果:
四、复制random单链表
链表结构比之前多一个random指针,随机指向一个节点,也可能指向空,如何对该链表进行克隆
- 利用HashMap对节点进行存储,key为老节点,value为克隆的新节点。分为两遍遍历,第一遍进行节点的复制,第二遍进行next与random节点的连接。时间复杂度 O(n) 空间复杂度(n)
- 在原节点后面加上克隆的节点,三遍遍历,第一遍进行节点的复制,并且将复制出来的节点连接到该节点的后面,克隆节点指向下一个旧节点。第二遍设置克隆节点的random节点。最后一遍将两个链表进行拆分。时间复杂度 O(n) 空间复杂度(1)
package LinkedList;
import java.util.HashMap;
import LinkedList.JudgementPalindrome.node;
public class RandomLinkClone {
public class node{
int val;
node next;
node random;
public node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
public node(int val, node next) {
this.val = val;
this.next = next;
this.random = null;
}
public node(int val, node next, node random) {
this.val = val;
this.next = next;
this.random = random;
}
public node insert(int val) {
node next = new node(val);
node cur = this;
while(cur.next != null) {
cur = cur.next;
}
cur.next = next;
return this;
}
public String toString() {
String ans = "";
node cur = this;
while(cur != null) {
ans += Integer.toString(cur.val) + " ";
if(cur.random != null) {
ans +="[" + cur.val + ".random-->" + Integer.toString(cur.random.val) + "] ";
}
cur = cur.next;
}
return ans;
}
}
public node cloneMethod1(node head) { // 时间复杂度 O(n) 空间复杂度(n)
if(head == null) return null;
node cur = head;
HashMap<node, node> map = new HashMap<>();
while(cur != null) { // 克隆节点
node new_node = new node(cur.val);
map.put(cur, new_node);
cur = cur.next;
}
cur = head; // 串联节点
while(cur != null) {
node new_node = map.get(cur);
if(cur.next != null) {
new_node.next = map.get(cur.next);
}
if(cur.random != null) {
new_node.random = map.get(cur.random);
}
cur = cur.next;
}
return map.get(head);
}
public node cloneMethod2(node head) { // 时间复杂度 O(n) 空间复杂度(1)
if(head == null) return null;
node cur = head;
while(cur != null) { //克隆链表
node new_node = new node(cur.val, cur.next);
cur.next = new_node; //将克隆节点接到原链表之后
cur = new_node.next;
}
cur = head;
while(cur != null) { //设置random节点
if(cur.random != null) {
cur.next.random = cur.random.next;
}
cur = cur.next.next;
}
cur = head; //拆分链表
node dumpy = new node(0); //哑结点 收集克隆节点
node clone = dumpy;
while(cur != null) {
clone.next = cur.next;
cur.next = cur.next.next;
cur = cur.next;
clone = clone.next;
}
return dumpy.next;
}
public static void main(String[] args) {
node head = new RandomLinkClone().new node(0);
head.insert(1).insert(2).insert(3).insert(4).insert(5).insert(6).insert(7).insert(8).insert(9);
head.random = head.next.next.next;
head.next.next.random = head;
head.next.random = head.next.next.next.next.next.next;
head.next.next.next.next.next.next.random = head.next.next.next.next.next.next.next;
System.out.println("原 串:" + head);
RandomLinkClone f = new RandomLinkClone();
System.out.println("复制串1:" + f.cloneMethod1(head));
System.out.println("原 串:" + head);
System.out.println("复制串2:" + f.cloneMethod2(head));
System.out.println("原 串:" + head);
}
}
运行结果:
五、链表相交
给定两个可能有环也可能无环的单链表,链表头分别为head1,head2,如果相交请返回相交的第一个节点,如果不相交返回null。
判断有环还是无环
- HashSet 时间复杂度O(n) 空间复杂度O(n)
- 快慢指针 时间复杂度O(n) 空间复杂度O(1)
package LinkedList;
import java.util.HashSet;
import LinkedList.PatitionList.node;
public class HavingRing {
public class node{
int val;
node next;
public node(int val) {
this.val = val;
this.next = null;
}
public node(int val, node next) {
this.val = this.val;
this.next = next;
}
public node insert(int val) {
node next = new node(val);
node cur = this;
while(cur.next != null) {
cur = cur.next;
}
cur.next = next;
return this;
}
public String toString() {
String ans = "";
node cur = this;
HashSet<node> set = new HashSet<>();
while(cur != null) {
if(set.contains(cur)) {
ans += "--> ";
ans += Integer.toString(cur.val) + "成环";
return ans;
}else {
set.add(cur);
ans += Integer.toString(cur.val) + " ";
cur = cur.next;
}
}
return ans + "无环";
}
}
public node hasRing1(node head) { //有环,返回第一个入环节点,无环,返回null 时间复杂度O(n) 空间复杂度O(n)
if(head == null) return null;
HashSet<node> set = new HashSet<>();
node cur = head;
while(cur != null) {
if(set.contains(cur)) {
return cur;
}else {
set.add(cur);
}
cur = cur.next;
}
return null;
}
public node hasRing2(node head) { //时间复杂度O(n) 空间复杂度O(1)
if(head == null || head.next == null) return null;
node fast = head;
node slow = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if(slow == fast) { //快慢指针相遇, 具体原因可以画图证明一下
node cur = head;
while(cur != slow) {
cur = cur.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
public static void main(String[] argv) {
node head1 = new HavingRing().new node(0);
head1.insert(1).insert(2).insert(3).insert(4).insert(5).insert(6).insert(7).insert(8).insert(9);
node cur = head1;
while(cur.next != null) {
cur = cur.next;
}
cur.next = head1.next.next.next.next;
System.out.println("有环串(head1):" + head1);
node head2 = new HavingRing().new node(0);
head2.insert(1).insert(2).insert(3).insert(4).insert(5).insert(6).insert(7).insert(8).insert(9);
System.out.println("无环串(head2):" + head2);
HavingRing f = new HavingRing();
System.out.println("------------------方法一----------------");
node f1 = f.hasRing1(head1);
String ans = "";
if(f1 == null) {
ans = "无环";
}else {
ans = Integer.toString(f1.val);
}
System.out.println("head1入环点:" + ans);
f1 = f.hasRing1(head2);
if(f1 == null) {
ans = "无环";
}else {
ans = Integer.toString(f1.val);
}
System.out.println("head2入环点:" + ans);
System.out.println("------------------方法二----------------");
node f2 = f.hasRing2(head1);
ans = "";
if(f2 == null) {
ans = "无环";
}else {
ans = Integer.toString(f2.val);
}
System.out.println("head1入环点:" + ans);
f2 = f.hasRing2(head2);
if(f2 == null) {
ans = "无环";
}else {
ans = Integer.toString(f2.val);
}
System.out.println("head2入环点:" + ans);
}
}
运行结果
链表相交
- 两个链表均无环,第一种情况:尾结点不相同则不可能相交。第二种情况:尾结点相同,一定相交,对链表长度进行计数,得到两个链表长度的差额cnt,长链表先走cnt次,之后和短链表一起走,最后一定在相交节点相遇。
- 一个有环,一个无环,不可能相交
- 两个都有环,入环节点相同:则与第一种一定相交的情况类似,计数相遇,但是本次并不是计算链表的长度,只计算到入环节点的长度即可。入环节点不同:不一定相交,在环内从第一个链表的入环节点开始走,如果走了一圈没有遇到第二个链表的入环节点则一定不相交,否则相交,返回任意一个入环节点即可。
package LinkedList;
import java.util.HashSet;
import LinkedList.HavingRing.node;
public class Intersection {
public class node{
int val;
node next;
public node(int val) {
this.val = val;
this.next = null;
}
public node(int val, node next) {
this.val = this.val;
this.next = next;
}
public node insert(int val) {
node next = new node(val);
node cur = this;
while(cur.next != null) {
cur = cur.next;
}
cur.next = next;
return this;
}
public String toString() {
String ans = "";
node cur = this;
HashSet<node> set = new HashSet<>();
while(cur != null) {
if(set.contains(cur)) {
ans += "--> ";
ans += Integer.toString(cur.val) + "成环";
return ans;
}else {
set.add(cur);
ans += Integer.toString(cur.val) + " ";
cur = cur.next;
}
}
return ans + "无环";
}
}
// 此代码写的较为冗余,不够美观,同时出口过多,读者可尝试进行简化。
public node isIntersection(node head1, node head2) {
node ring1 = hasRing(head1);
node ring2 = hasRing(head2);
// 两者都无环
if(ring1 == null && ring2 == null) {
node cur = head1;
int cnt = 0;
while(cur.next != null) {
++cnt;
cur = cur.next;
}
node e1 = cur; // head1 的尾节点
cur = head2;
while(cur.next != null) {
--cnt;
cur = cur.next;
}
if(e1 != cur) { //相交链表尾部必相等
return null;
}
cur = cnt > 0? head1: head2;
node cur_2 = cur == head1? head2: head1;
cnt = Math.abs(cnt);
for(int i=0; i<cnt; ++i) {
cur = cur.next;
}
while(cur != cur_2) {
cur = cur.next;
cur_2 = cur_2.next;
}
return cur;
}else if(ring1 != null && ring2 != null) {
node cur = null;
if(ring1 == ring2) { //入环节点相同
cur = head1;
int cnt = 0;
while(cur != ring1) {
++cnt;
cur = cur.next;
}
node e1 = cur; // head1 的尾节点
cur = head2;
while(cur != ring2) {
--cnt;
cur = cur.next;
}
cur = cnt > 0? head1: head2;
node cur_2 = cur == head1? head2: head1;
cnt = Math.abs(cnt);
for(int i=0; i<cnt; ++i) {
cur = cur.next;
}
while(cur != cur_2) {
cur = cur.next;
cur_2 = cur_2.next;
}
return cur;
}
cur = ring1.next;
while(cur != ring1) {
if(cur == ring2) { //相交
return ring1;
}
cur = cur.next;
}
return null;
}
return null; //一个有环一个无环不可能相交
}
public node hasRing(node head) {
if(head == null || head.next == null) return null;
node fast = head;
node slow = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if(slow == fast) { //快慢指针相遇
node cur = head;
while(cur != slow) {
cur = cur.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
public static void main(String[] args) {
node head1 = new Intersection().new node(0);
head1.insert(1).insert(2).insert(3).insert(4).insert(5).insert(6).insert(7).insert(8).insert(9);
node head2 = new Intersection().new node(10);
head2.insert(11).insert(12).insert(13).insert(14).insert(15).insert(16).insert(17).insert(18).insert(19);
node cur = head2;
while(cur.next != null) {
cur = cur.next;
}
cur.next = head1.next.next.next.next.next;
Intersection f = new Intersection();
System.out.println("-----------两个无环的相交串---------------------");
System.out.println("串1:" + head1);
System.out.println("串2:" + head2);
node ans = f.isIntersection(head1, head2);
if(ans != null) {
System.out.println("相交于" + ans.val);
}else {
System.out.println("不相交");
}
cur.next = null;
System.out.println("-----------两个无环的不相交串---------------------");
System.out.println("串1:" + head1);
System.out.println("串2:" + head2);
ans = f.isIntersection(head1, head2);
if(ans != null) {
System.out.println("相交于" + ans.val);
}else {
System.out.println("不相交");
}
cur.next = head2.next.next.next;
cur = head1;
while(cur.next != null) {
cur = cur.next;
}
cur.next = head2.next.next;
System.out.println("-----------两个有环的相交串入环节点相同---------------------");
System.out.println("串1:" + head1);
System.out.println("串2:" + head2);
ans = f.isIntersection(head1, head2);
if(ans != null) {
System.out.println("相交于" + ans.val);
}else {
System.out.println("不相交");
}
cur.next = head2.next.next.next.next.next;
System.out.println("-----------两个有环的相交串入环节点不相同---------------------");
System.out.println("串1:" + head1);
System.out.println("串2:" + head2);
ans = f.isIntersection(head1, head2);
if(ans != null) {
System.out.println("相交于" + ans.val);
}else {
System.out.println("不相交");
}
cur.next = head1.next.next.next;
System.out.println("-----------两个有环的不相交串---------------------");
System.out.println("串1:" + head1);
System.out.println("串2:" + head2);
ans = f.isIntersection(head1, head2);
if(ans != null) {
System.out.println("相交于" + ans.val);
}else {
System.out.println("不相交");
}
cur.next = null;
System.out.println("-----------一个有环 一个无环的不相交串---------------------");
System.out.println("串1:" + head1);
System.out.println("串2:" + head2);
ans = f.isIntersection(head1, head2);
if(ans != null) {
System.out.println("相交于" + ans.val);
}else {
System.out.println("不相交");
}
}
}
运行结果
六、删除节点(只给需要删除的节点不给头结点)
只给需要删除的节点是不可能做到将节点删除的,能做到的只是借尸还魂:就是将该节点后面的节点删除,同时将给定需要删除的节点的值更改成该节点后面节点的值,同时next指针指向下一个的下一个节点。但是该方法不能删除尾节点。
package LinkedList;
public class DeleteNode {
public class node{
int val;
node next;
public node(int val) {
this.val = val;
this.next = null;
}
public node(int val, node next) {
this.val = this.val;
this.next = next;
}
public node insert(int val) {
node next = new node(val);
node cur = this;
while(cur.next != null) {
cur = cur.next;
}
cur.next = next;
return this;
}
public String toString() {
String ans = "";
node cur = this;
while(cur != null) {
ans += Integer.toString(cur.val) + " ";
cur = cur.next;
}
return ans;
}
}
public void deleteNode(node dn) { //此方法无法物理删除头节点,所以头结点的地址不会变,不需要进行返回
if(dn == null) {
System.err.println("不能删除空节点");
return;
}
node next = dn.next;
if(dn.next == null) {
System.err.println("无法删除尾节点");
}else {
dn.val = next.val;
dn.next = next.next;
}
}
public static void main(String[] args) {
node head = new DeleteNode().new node(0);
head.insert(1).insert(2).insert(3).insert(4).insert(5).insert(6).insert(7).insert(8).insert(9);
node cur = head;
while(cur.next != null) {
cur = cur.next;
}
DeleteNode f = new DeleteNode();
System.out.println("原串:" + head);
f.deleteNode(head);
System.out.println("删除头节点后:" + head);
f.deleteNode(head.next.next.next);
System.out.println("删除中间节点后:" + head);
f.deleteNode(cur);
System.out.println("删除尾节点后:" + head);
f.deleteNode(null);
System.out.println("删除空节点后:" + head);
}
}
运行结果
总结
以上便是关于链表基础题的全部内容,前面的几道题都用了两种解法,解法的时间复杂度相同,不同点在于空间复杂度,请大家切记在笔试和面试中选择正确的方法,来为自己赢得加分。
1. 对于笔试,不用太在乎空间复杂度,一切为了时间复杂度
2. 对于面试,时间复杂度依然放在第一位,但是一定要找到空间最省的方法,给面试官留下更加深刻的印象