Java 环形链表及约瑟夫问题

环形链表及约瑟夫问题

接上篇的单联表,这篇主要写一下环形链表和约瑟夫问题

  1. 环形链表

    环形链表的思路: 把传进来的链表遍历到尾巴,然后尾部的next指向头部即可

//把传进来的链表变成环形链表
public Student cirleLink(Student head){
    Student temp = head;
    while (true){
        if(temp.next == null){
            break;
        }
        temp = temp.next;
    }
    temp.next = head;
    return head;
}
  1. 约瑟夫问题

    /**
         *  约瑟夫问题
         * @param head 储存数据的链表
         * @param m 每隔M个就干掉
         * @param no 从编号No开始算起
         * @return
         */
    public ArrayList josephu(Student head,int m,int no){
        if (head.next == null){
            return null;
        }
        //创建一个存放编号的数组
        ArrayList<Integer> noArray = new ArrayList<>();
        //创建一个辅助指针,用来储存被干掉的节点之前的一个节点
        Student temp = null;
        //把传进来的head变成环形链表,这里head.next是去掉头部
        Student circle = cirleLink(head.next);
        //从指定编号算起
        while (true){
            if(circle.no == no){
                break;
            }
            circle = circle.next;
        }
        while (true){
            //如果circle的下一个以及下下个都等于temp的话,说明这个环形链表只剩一个节点
            if(circle.next == temp && circle.next.next == temp){
                noArray.add(temp.no);
                break;
            }
            //循环每隔 m 个数要干掉的节点的前一个
            for (int i = 0; i < m - 1; i++) {
                //当 i 循环到最后一个的时候,此时的temp等于要被干掉的节点的前一个
                temp = circle;
                if(i == m - 2){
                    //放入要被干掉的节点的编号
                    noArray.add(circle.next.no);
                    //将circle的下一个节点指向下下个节点上,这样被干掉的节点就不会再被指向了
                    circle.next = circle.next.next;
                    break;
                }
                //往后移
                circle = circle.next;
            }
            //干掉节点之后,circle往后移动一个然后继续
            circle = circle.next;
        }
        return noArray;
    }
    

    灵魂画图
    在这里插入图片描述

约瑟夫环问题是这样的:在一个有n个人的圈子里,从第一个人开始报数,每个人报到k后出圈,然后下一个人继续,直到最后剩下的人赢得游戏。你可以使用Java链表来模拟这个过程,每个节点代表一个人,并维护一个指向下一个节点的引用。 以下是一个简单的Java代码示例,使用单向链表实现约瑟夫环问题: ```java public class JosephusRing { static class Node { int value; Node next; public Node(int value) { this.value = value; this.next = null; } } public static Node josephusProblem(int n, int k) { if (n <= 0 || k <= 0) { throw new IllegalArgumentException("Invalid input: n and k must be positive integers"); } // 创建一个长度为n的环形链表 Node[] nodes = new Node[n]; for (int i = 0; i < n; i++) { nodes[i] = new Node(i + 1); if (i != 0) { nodes[i - 1].next = nodes[i]; } else { nodes[n - 1].next = nodes[0]; // 给最后一个节点指向前一个节点形成环 } } // 开始计数并删除节点 Node current = nodes[0]; while (nodes.length > 1) { current = current.next; current = current.next % k == 0 ? current : current.next; // 报数达到k就跳过当前节点 } return current; } public static void main(String[] args) { int n = 7; // 人数 int k = 3; // 报数步长 System.out.println(josephusProblem(n, k).value); // 输出最后幸存者的位置 } } ``` 在这个代码中,`josephusProblem`函数创建了一个环形链表,然后通过循环移除节点,直到只剩下一个。当找到的节点需要跳过k个位置时,它会直接跳到下一个节点,直到找到第一个不需要跳过的节点,这就是幸存者。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值