算法提高 奥运会开幕式

问题描述

学校给高一(三)班分配了一个名额,去参加奥运会的开幕式。每个人都争着要去,可是名额只有一个,怎么办?班长想出了一个办法,让班上的所有同学(共有n个同学)围成一圈,按照顺时针方向进行编号。然后随便选定一个数m,并且从1号同学开始按照顺时针方向依次报数,1, 2, …, m,凡报到m的同学,都要主动退出圈子。然后不停地按顺时针方向逐一让报出m者出圈,最后剩下的那个人就是去参加开幕式的人。

要求

用环形链表的方法来求解。所谓环形链表,即对于链表尾结点,其next指针又指向了链表的首结点。基本思路是先创建一个环形链表,模拟众同学围成一圈的情形。然后进入循环淘汰环节,模拟从1到m报数,每次让一位同学(结点)退出圈子。

输入格式

输入只有一行,包括两个整数n和m,其中n和 m的含义如上所述。

输出格式

输出只有一个整数,即参加开幕式的那个人的编号。

输入输出样例

样例输入
8 3
样例输出
7

解答

emm之前做没看具体要求,使用了数组内取余循环做法,解题如下:

import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[] nums = new int[n];
        for (int i = 0; i < nums.length; i++) {
    
    
            nums[i] = i+1;
        }
        // 辅助
        int index = 0;
        // 淘汰人数
        int out = 0;
        while (out < n-1) {
    
    
            int temp = 0;
            while (temp < m) {
    
    
                if (nums[index] != 0) temp++;
                index = (++index)%n;
            }
            if (index != 0)
                nums[index-1] = 0;
            else nums[n-1] = 0;
            out++;
        }
        for (int i = 0; i < nums.length; i++) {
    
    
            if (nums[i] != 0) {
    
    
                System.out.print(nums[i]);
                break;
            }
        }
    }
}

再写一个单向环形链表做法,做法如下:

import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 读入数据
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        scanner.close();
        // 初始化
        CircleLink circleLink = new CircleLink(1);
        for (int i = 2; i <= n; i++) {
    
    
            circleLink.addNode(i);
        }
        // 开始循环去除
        Node temp = circleLink.getFirst();
        while (circleLink.getSize() > 1) {
    
    
            for (int i = 1; i < m; i++) {
    
    
                temp = temp.getNext();
            }
            circleLink.deleteNode(temp);
            temp = temp.getNext();
        }
        // 输出参加者
        System.out.println(circleLink.getFirst().getValue());
    }
}

/**
 * 单向环形链表节点
 */
class Node {
    
    
    private int value = 0;
    private Node next = null;

    public Node() {
    
    
    }

    public Node(int value) {
    
    
        this.value = value;
    }

    public int getValue() {
    
    
        return value;
    }

    public void setValue(int value) {
    
    
        this.value = value;
    }

    public Node getNext() {
    
    
        return next;
    }

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

/**
 * 单向环形链表
 */
class CircleLink {
    
    
    private Node first = null;
    private int size = 0;

    public CircleLink(int value) {
    
    
        first = new Node(value);
        first.setNext(first);
        size = 1;
    }

    /**
     * 添加
     * @param value
     */
    public void addNode(int value) {
    
    
        Node temp = first;
        // 走到链尾
        while (temp.getNext() != first) temp = temp.getNext();
        Node node = new Node(value);
        temp.setNext(node);
        node.setNext(first);
        size++;
    }

    /**
     * 删除
     * @param node
     */
    public void deleteNode(Node node) {
    
    
        Node temp = first;
        while (temp.getNext() != node) temp = temp.getNext();
        if (node == first) {
    
    
            first = node.getNext();
        }
        temp.setNext(node.getNext());
        size--;
    }

    public Node getFirst() {
    
    
        return first;
    }

    public int getSize() {
    
    
        return size;
    }
}

猜你喜欢

转载自blog.csdn.net/L333333333/article/details/104087489