链表顺序表常见面试题(1)——Java语言实现

从尾到头打印单链表(知道链表的头结点)
针对从尾到头打印链表,我们可以采用两种方式:
(1)利用栈的特性(先进后出),遍历链表将元素入栈,当链表为空时,依次出栈。
(2)采用递归方法,但是当数据量足够大时可导致栈溢出。

 
 
  • 1
  • 2
  • 3

这里写图片描述

package com.struct.interview_question.list_interview_question;
//定义链表的节点
public class ListNode {
    public Object data;
    public ListNode nextNode;
    public ListNode(Object data) {
        this.data = data;
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
package com.struct.interview_question.list_interview_question.listreverse;

import com.struct.interview_question.list_interview_question.ListNode;

import java.util.Stack;
//从尾到头打印链表
public class ReverseList {
    //使用栈来操作
    public static void printListReverseByStack(ListNode headNode){
        Stack<ListNode> stack = new Stack<ListNode>();
        //将表中的数据入栈
        while (headNode!=null){
            stack.push(headNode);
            headNode = headNode.nextNode;
        }

        //栈非空则弹出栈顶元素
        while (!stack.isEmpty()){
            System.out.print(stack.pop().data+" ");
        }
    }

    //方法2:采用递归方式
    public void printListReverseByRecursive(ListNode headNode){
        if(headNode.nextNode!=null){
            printListReverseByRecursive(headNode.nextNode);
        }
        System.out.print(headNode.data+" ");
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
本文中我将采用测试框架对代码进行测试。
step1:首先我们构建的Maven项目
step2:在pom文件中加入测试框架的依赖

 
 
  • 1
  • 2
<dependencies>
        <!--单元测试依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
step3:进行测试

 
 
  • 1
package com.struct.listinterview;

import com.struct.interview_question.list_interview_question.ListNode;
import com.struct.interview_question.list_interview_question.delete_headnode.DeleteNotTailNode;
import com.struct.interview_question.list_interview_question.listreverse.ReverseList;
import org.junit.Test;

//测试代码
public class ListInterviewQuestionTest {
//栈实现从尾到头打印链表的测试
    @Test
    public void test_PrintListReverseByStack(){
        ReverseList reverseList = new ReverseList();
        ListNode listNode = new ListNode(1);
        listNode.nextNode = new ListNode("demon");
        listNode.nextNode.nextNode = new ListNode('a');
        reverseList.printListReverseByStack(listNode);
    }
//递归实现从尾到头打印链表的测试
    @Test
    public void test_PrintListReverseByRecursive(){
        ReverseList reverseList = new ReverseList();
        ListNode listNode = new ListNode(1);
        listNode.nextNode = new ListNode("demon");
        listNode.nextNode.nextNode = new ListNode('a');
        reverseList.printListReverseByRecursive(listNode);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
不遍历链表,删除一个无头单链表的非尾节点
删除指定的非尾节点:
step1:我们首先创建一个新的节点curNode指定要删除节点的
下一个节点
step2:将此节点的值赋给要删除节点node
step3:将要删除节点node的下一个节点指向新建节点
的下一个节点curNode.next

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

package com.struct.interview_question.list_interview_question.delete_headnode;

import com.struct.interview_question.list_interview_question.ListNode;

public class DeleteNotTailNode {
    //不遍历链表删除无头单链表的非尾节点(参数为要删除的节点)
    public void deleteNotTailNode(ListNode node){
        ListNode curNode = null;
        if(node.nextNode!=null) {
            curNode = node.nextNode;
            node.data = curNode.data;
            node.nextNode = curNode.nextNode;
        }
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
 @Test
    public void test_DeleteNotTailNode(){
        ListNode listNode = new ListNode(1);
        listNode.nextNode = new ListNode("demon");
        listNode.nextNode.nextNode = new ListNode('a');
        DeleteNotTailNode deleteNotTailNode = new DeleteNotTailNode();
        deleteNotTailNode.deleteNotTailNode(listNode.nextNode);
        //用于验证是否删除成功
        ReverseList reverseList = new ReverseList();
        reverseList.printListReverseByRecursive(listNode);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
在无头单链表的一个节点前插入新的节点
在节点前进行插入节点,我们并不能和以往一样改变节点的
指向就好,而是首先创建新的的节点newNode,使得节点指向
指定要插入节点node的下一个节点node.next,然后再使得node
指向新的节点newNode,最后,我们应当对node和newNode的值进行交换。

 
 
  • 1
  • 2
  • 3
  • 4

这里写图片描述

package com.struct.interview_question.list_interview_question.insertnode;
import com.struct.interview_question.list_interview_question.ListNode;

public class InsertNode {
    //在无头链表的任意节点前插入节点(不遍历链表)
    public void insertNodePre(ListNode node){
        ListNode newNode = new ListNode("lll");
        //新节点指向要插入节点的下一个节点
        newNode.nextNode = node.nextNode;
        //指点节点指向新的节点
        node.nextNode = newNode;
        //交换节点的值
        Object curData = node.data;
        node.data = newNode.data;
        newNode.data = curData;
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  @Test
    public void test_InsertNodePre(){
        ListNode listNode = new ListNode(1);
        listNode.nextNode = new ListNode("demon");
        listNode.nextNode.nextNode = new ListNode('a');
        InsertNode insertNode = new InsertNode();
        insertNode.insertNodePre(listNode.nextNode);
        //用于验证是否删除成功
        ReverseList reverseList = new ReverseList();
        reverseList.printListReverseByRecursive(listNode);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
单链表实现约瑟夫环(JosephCircle)
首先我们来解释一下约瑟夫:
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。
从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,
数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列

 
 
  • 1
  • 2
  • 3
  • 4

step1:首先我们应该用单链表创建一个环
step2:设置环的长度,及要被淘汰的数字(从1开始计数),每次淘汰一个,我们应该改变tail的指向,
即tail.next = tail.next.next;

 
 
  • 1
  • 2
  • 3

这里写图片描述

package com.struct.interview_question.list_interview_question.listjosephcircle;

import com.struct.interview_question.list_interview_question.ListNode;

public class ListJosephCircle{
//单链表解决约瑟夫环问题
    public void listJosephCircle(int perNum, int exitNum, ListNode tail){
        while(tail!=tail.nextNode){
            for(int i =1 ;i < exitNum;i++)
                //移动tail的指向
                tail = tail.nextNode;
            //删除第m个节点
            System.out.println(tail.nextNode.data+" ");
            //将tail的next指向要删除节点的下一个节点
            tail.nextNode = tail.nextNode.nextNode;
        }
        System.out.println("幸运者为:"+tail.data);
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
 @Test
    public void test_ListJosephCircle(){
    //构建约瑟夫环
        ListNode head = new ListNode(0);
        head.nextNode = new ListNode(1);
        head.nextNode.nextNode = new ListNode(2);
        head.nextNode.nextNode.nextNode = new ListNode(3);
        head.nextNode.nextNode.nextNode.nextNode = new ListNode(4);
        head.nextNode.nextNode.nextNode.nextNode.nextNode = new ListNode(5);
        ListNode tail = head.nextNode.nextNode.nextNode.nextNode.nextNode;
        tail.nextNode = head;
        //调用方法
        ListJosephCircle listJosephCircle = new ListJosephCircle();
        listJosephCircle.listJosephCircle(6,2,tail);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值