用Java语言写,还有思路逻辑结构 物理结构

约瑟夫环问题有 n 个人编号为1~ n ,排成一个环,从1号人开始从1到 m 报数,报到 m 的人离开该环,从下一个人开始继续从1到 m 报数,报到 m 的人离开该环,这样一直进行下去,直到最终剩余 p 个人。从键盘输入 n 、 m 、 p ,要求 n >=2、 m >=2、 l <= p < n ,输出最终剩余的 p 个初始编号。例如:输入 n 、 m 、 p 依此为,4、3、2,则输出为1和4。

有帮助的 采纳一下

import java.util.Scanner;

public class Josephus {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入人数n:");
        int n = sc.nextInt();
        System.out.println("请输入报数m:");
        int m = sc.nextInt();
        System.out.println("请输入最后剩余人数p:");
        int p = sc.nextInt();
        
        if (n < 2 || m < 2 || p <= 0 || p > n) {
            System.out.println("输入参数错误!");
            return;
        }
        
        // 存储编号,开始从1到n
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = i + 1;
        }
        
        int count = 0;  // 报数
        int index = 0;  // 数组下标
        
        while (n > p) {
            // 报数,计数器+1
            count++;  
            // 如果报到m,则从数组中删除该元素,人数-1
            if (count == m) {
                nums[index] = 0;
                n--;
                count = 0; // 重新开始报数
                continue;
            }
            
            // 下标移动到下一个元素
            index++;
            if (index == n) index = 0;  // 如果下标超出范围,则回到0
            
            // 如果下一个元素为0,则继续移动,知道找到非0元素
            while (nums[index] == 0) {
                index++;
                if (index == n) index = 0;
            }
        }
        
        // 输出最终剩余人的编号
        for (int num : nums) {
            if (num != 0) System.out.print(num + " ");
        }
    } 
}

Java解决约瑟夫环问题(通俗易懂版)_java 约瑟夫环问题_LCW0102的博客-CSDN博客 约瑟夫环问题: 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后 结果+1即为原问题的解。解法一:利用链表 我们可以把每一个人变成一个链表,然后不断地循环这个链表。每次删除一个结点,直到最终只剩下一个结点的时候就表示我们找到个!解_java 约瑟夫环问题 https://blog.csdn.net/LCW0102/article/details/125182664

可参考

public class Person {
    private int number;

    public Person(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }
}

public class CircularLinkedList {
    private Node head;
    private int size;

    public void addPerson(int number) {
        Person person = new Person(number);
        Node newNode = new Node(person);

        if (head == null) {
            head = newNode;
            head.setNext(head);
        } else {
            Node current = head;
            while (current.getNext() != head) {
                current = current.getNext();
            }
            current.setNext(newNode);
            newNode.setNext(head);
        }
        size++;
    }

    public void removePerson(int m) {
        Node current = head;
        Node previous = null;

        while (size > 1) {
            for (int i = 1; i < m; i++) {
                previous = current;
                current = current.getNext();
            }

            previous.setNext(current.getNext());
            current = current.getNext();
            size--;
        }
    }

    public List<Integer> getRemainingPeople(int p) {
        List<Integer> remaining = new ArrayList<>(p);
        Node current = head;

        for (int i = 0; i < p; i++) {
            remaining.add(current.getPerson().getNumber());
            current = current.getNext();
        }
        return remaining;
    }

    private static class Node {
        private Person person;
        private Node next;

        public Node(Person person) {
            this.person = person;
        }

        public Person getPerson() {
            return person;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }
}

public class JosephusProblem {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("输入人数 (n): ");
        int n = scanner.nextInt();

        System.out.print("输入计数值 (m): ");
        int m = scanner.nextInt();

        System.out.print("输入剩余人数(p): ");
        int p = scanner.nextInt();

        scanner.close();

        if (n < 2 || m < 2 || p < 1 || p >= n) {
            System.out.println("输入无效");
            return;
        }

        CircularLinkedList circularLinkedList = new CircularLinkedList();

        for (int i = 1; i <= n; i++) {
            circularLinkedList.addPerson(i);
        }

        circularLinkedList.removePerson(m);

        List<Integer> remainingPeople = circularLinkedList.getRemainingPeople(p);

        System.out.println("剩余人员: " + remainingPeople);
    }
}

思路:

  1. 首先创建一个循环链表,其中每个节点表示一个人,并为每个人设置一个初始编号。
  2. 定义一个计数器,从1开始计数,当计数器的值等于m时,表示当前报数到m。
  3. 当计数器的值等于m时,移除当前节点(即当前报数到m的人),并将计数器重置为1。
  4. 重复步骤3,直到只剩下p个人停止移除操作。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("请输入 n:");
        int n = input.nextInt();
        System.out.print("请输入 m:");
        int m = input.nextInt();
        System.out.print("请输入 p:");
        int p = input.nextInt();
        input.close();

        List<Integer> list = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            list.add(i);
        }

        int count = 0;
        int index = 0;
        while (list.size() > p) {
            int num = list.get(index);
            count++;
            if (count == m) {
                list.remove(index);
                count = 0;
                index--;
            }
            index = (index + 1) % list.size();
        }

        System.out.println(p);
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i) + " ");
        }
    }
}

看下面代码,这个是Java语言编写的解决约瑟夫环问题的代码,包括思路逻辑结构和物理结构的实现:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class JosephusProblem {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入总人数 n: ");
        int n = scanner.nextInt();

        System.out.print("请输入报数上限 m: ");
        int m = scanner.nextInt();

        System.out.print("请输入最终剩余人数 p: ");
        int p = scanner.nextInt();

        if (n < 2 || m < 2 || p >= n) {
            System.out.println("输入不符合要求!");
            return;
        }

        List<Integer> people = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            people.add(i);
        }

        int currentIndex = 0;
        while (people.size() > p) {
            currentIndex = (currentIndex + m - 1) % people.size();
            people.remove(currentIndex);
        }

        System.out.println("最终剩余的 " + p + " 个人的初始编号为:");
        for (int number : people) {
            System.out.print(number + " ");
        }
    }
}

思路逻辑结构:

  1. 从键盘输入总人数 n、报数上限 m、最终剩余人数 p。
  2. 检查输入的合法性,确保 n >= 2、m >= 2、l <= p < n。
  3. 创建一个列表(ArrayList)来表示约瑟夫环中的人,初始时包含从1到n的编号。
  4. 使用循环,每次循环中进行以下操作,直到剩余人数不大于 p:
    • 根据报数上限 m 和当前位置,计算出下一个要离开的人的索引。
    • 在列表中移除该人。
  5. 输出最终剩余的 p 个人的初始编号。

物理结构:
在物理结构上,使用了一个ArrayList来表示约瑟夫环中的人。ArrayList是一个可变长度的数组,可以动态添加、删除元素。通过列表中元素的索引,实现了约瑟夫环的逻辑结构。每次删除一个人时,根据索引进行移除操作,模拟人离开约瑟夫环的过程。最后,剩余的人的初始编号通过遍历列表输出。

思路:这一题,就是n个人按顺时针占成一圈.从第一个位置开始数,数到k就将对应的位置上的人踢出局。不断地重复次操作,直到最后剩下最后一个人,然后输出这个人地序号。

img