单链表的常见面试题有如下:
1)求单链表中有效节点的个数
2)查找单链表中的倒数第k个结点 【新浪面试题】
3)单链表的反转【腾讯面试题,有点难度】
4)从尾到头打印单链表 【百度,要求方式1:反向遍历 。 方式2:Stack栈】
下面用代码逐一实现
问题一:求单链表中有效节点的个数
此题较为简单,声明一个方法即可
//返回链表的有效长度,如果有头结点就忽略
public static int getLength(HeroNode head){
if(head.next == null){
System.out.println("该链表为空");
}
HeroNode temp = head.next;
int length = 0;
while (temp != null){
length++;
temp = temp.next;
}
return length;
}
问题二:查找单链表中的倒数第k个结点
//查找单链表中的倒数第k个结点 【新浪面试题】
//思路:1.定义index表示倒数第index个节点
//2.编写一个方法接收head节点,同时接收index
//3.把链表从头到尾遍历,得到链表的总长度getLength()
//4.得到size,从头开始遍历到第size - index个即可
public static HeroNode findLastIndexNode(HeroNode head,int index){
if(head.next == null){
return null;
}
//第一次遍历得到链表长度
int size = getLength(head);
//第二次遍历size - index个
//先对index做一个校验
if(index <= 0 || index > size){
return null;
}
HeroNode temp = head.next;
for (int i = 0; i < size - index; i++) {
temp = temp.next
}
return temp;
}
此段代码进行了两次遍历,第一次找出链表的有效长度,第二次遍历第(长度-倒数)个元素,从而以正序的方式,找到倒序的数据,个人觉得两次遍历有点复杂,但是也想不到更好的方法,暂且搁置。
问题三:单链表的反转【腾讯面试题,有点难度】
//翻转单链表
//思路:1.定义一个reverseHead = new HeroNode()
//2.遍历原链表,每遍历一个数据,就将其取出,放在新链表的最前端(头插法)
//3.原来链表的head.next = reverseHead.next
public static void reverseList(HeroNode head){
//如果当前链表为空,或只有一个节点,无需翻转
if(head.next == null || head.next.next == null){
return;
}
HeroNode temp = head.next;
HeroNode next = null;//指向当前temp的下一个节点
HeroNode reverseHead = new HeroNode(0,"","");
//遍历原链表,每遍历一个数据,就将其取出,放在新链表的最前端
while (temp != null){
next = temp.next;//先保存当前节点的下一个节点,后面需要使用
temp.next = reverseHead.next;//将temp的下一个节点指向新链表的前端
reverseHead.next = temp;//将temp连接到新的链表上
temp = next;
}
head.next = reverseHead.next;
}
讲实话,这一段翻转的思路我是懂的,图也能画出来。But,代码我是真的不理解,更别说敲了,我需要找点资料自己消化一下,有理解的大佬也可以在下面评论帮我缕缕。
看了下《大话数据结构》上面的介绍
还是一知半解,于是自己在草稿纸上画了画,瞬间通透,下面我用visio演示一下头插法的流程
终归是理解了,但是让我自己敲,还是敲不出来啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
为了掌握这个知识点,我自己重敲了一遍
package com.sanjin.exer;
/**
* @author sanjin
* @create 2021-12-19 12:46
*/
public class reverseLinkedListTest {
public static void main(String[] args) {
Node node1 = new Node(1, "小明", true);
Node node2 = new Node(2, "小刚", true);
Node node3 = new Node(3, "小美", false);
Node node4 = new Node(4, "小丽", false);
LinkedList linkedList = new LinkedList();
linkedList.addNode(node1);
linkedList.addNode(node2);
linkedList.addNode(node3);
linkedList.addNode(node4);
System.out.println("初始链表为:");
linkedList.show();
linkedList.reverseList(linkedList.getHead());
System.out.println("翻转后的链表为:");
linkedList.show();
}
}
class LinkedList{
private Node head = new Node(0,"",false);
public Node getHead() {
return head;
}
//翻转链表
public void reverseList(Node head){
if(head.next == null || head.next.next == null){
return;
}
Node temp = head.next;
Node next = null;
Node reverseHead = new Node(0,"",false);
while (temp != null){
next = temp.next;
temp.next = reverseHead.next;
reverseHead.next = temp;
temp = next;
}
head.next = reverseHead.next;
}
//在链表中按顺序添加元素
public void addNode(Node node){
Node temp = head;
boolean flag = false;
while (true){
if(temp.next == null){
break;
}
if(temp.next.num > node.num){
break;
}else if(temp.next.num == node.num){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
System.out.println("要添加的元素已经存在");
}else {
node.next = temp.next;
temp.next = node;
}
}
//遍历链表
public void show(){
if(head.next == null){
System.out.println("链表为空");
}
Node temp = head.next;
while (true){
if(temp == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
class Node{
public int num;
public String name;
public boolean isMale;
public Node next;
public Node(int num, String name, boolean isMale) {
this.num = num;
this.name = name;
this.isMale = isMale;
}
@Override
public String toString() {
return "Node{" +
"num=" + num +
", name='" + name + '\'' +
", isMale=" + isMale +
'}';
}
}
运行结果为:
可是让我查都不看,纯敲,我真的做不到,哭了。
问题四:从尾到头打印单链表 【百度,要求方式1:反向遍历 。 方式2:Stack栈】
方式一没啥可说的,做好问题三,直接打印即可。但是这种方法会改变原链表的结构
利用栈的先进后出性实现:
//从尾到头打印单链表 【百度,要求:Stack栈】
public static void reversePrint(HeroNode head){
if(head.next == null){
return;
}
//创建一个栈
Stack<HeroNode> stack = new Stack<>();
HeroNode temp = head.next;
//将链表所有的节点压入栈中
while (temp != null){
stack.push(temp);
temp = temp.next;
}
//将栈中的节点进行打印pop
while (stack.size() > 0){
System.out.println(stack.pop());
}
}
整体不难,思路就是创建一个栈,利用辅助变量将链表中的元素一个个压入栈中,最后pop栈,实现逆序打印,且不改变原链表的结构。
痛苦面具!!!!!!!!!!!!!!!!!!!!!!!!!!!!