约瑟夫算法问题

题目描述

n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 1 开始报数,数到 m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

输入格式

输入两个整数 n,m

输出格式

输出一行 n 个整数,按顺序输出每个出圈人的编号

1 ≤ m , n ≤ 100 1\leq m, n \leq 100 1m,n100

样例
输入10 3; 输出3 6 9 2 7 1 8 5 10 4
代码:(单链表、双指针解法)
public class Josepfu {

    public List<Integer> handleJosepfuQuestion(int personCount, int m) {
        if (m <= 0) {
            throw new RuntimeException("不可移动小于等于0步");
        }
        if (personCount <= 0) {
            throw new RuntimeException("不可节点数小于等于0");
        }
        CircleLinkList linkList = makeCircleList(personCount);
        List<Integer> list = new ArrayList<Integer>();
        ListNode node = linkList.head();

        while (node != node.next) {
            ListNode popNode = popNode(node, m);
            list.add(popNode.num);
            node = popNode.next;
        }
        list.add(node.num);
        return list;
    }

    /**
     * 算上自己,移动m步
     * @param node
     * @param m
     * @return
     */
    private ListNode popNode(ListNode node, int m) {
        if (node == node.next) return node;
        //找到node的上一个node
        ListNode helperNode = node;
        while(helperNode.next != node) {
            helperNode = helperNode.next;
        }

        for (int i = 1; i < m; i++) {
            node = node.next;
            helperNode = helperNode.next;
        }
        helperNode.next = node.next;
        return node;
    }

    private CircleLinkList makeCircleList(int personCount) {
        CircleLinkList circleLinkList = new CircleLinkList();
        for (int i = 0; i < personCount; i++) {
            ListNode node = new ListNode(i, null);
            circleLinkList.add(node);
        }
        return circleLinkList;
    }


    static class CircleLinkList {
        private int size;
        private ListNode tail;

        public CircleLinkList() {
            this.tail = null;
            this.size = 0;
        }

        public void add(ListNode node) {
            if (tail == null) {
                tail = node;
                tail.next = node;
                size++;
            } else {
                ListNode temp = tail.next;
                tail.next = node;
                node.next = temp;
                tail = node;
            }
        }

        public ListNode head() {
            if (tail == null) return null;
            return tail.next;
        }

        public void printList() {
            if (tail == null) return;
            ListNode head = tail.next;
            ListNode temp = tail.next;
            while (true) {
                System.out.println(temp.num);
                temp = temp.next;
                if (temp == head) return;
            }
        }

        public int size() {
            return this.size;
        }

    }

    static class ListNode {
        int num;
        ListNode next;

        public ListNode(int num, ListNode next) {
            this.num = num;
            this.next = next;
        }
    }
}

测试用例:
public class JosepfuTest {

    @Test
    public void handleJosepfuQuestion() {
        Josepfu josepfu = new Josepfu();
        List<Integer> list = josepfu.handleJosepfuQuestion(6, 4);
        assertEquals(3, (int)list.get(0));
        assertEquals(1, (int)list.get(1));
        assertEquals(0, (int)list.get(2));
        assertEquals(2, (int)list.get(3));
        assertEquals(5, (int)list.get(4));
        assertEquals(4, (int)list.get(5));
        System.out.println(list);

    }

    private Josepfu.CircleLinkList prepareData() {
        Josepfu.CircleLinkList linkList = new Josepfu.CircleLinkList();
        Josepfu.ListNode node1 = new Josepfu.ListNode(1, null);
        Josepfu.ListNode node2 = new Josepfu.ListNode(2, null);
        Josepfu.ListNode node3 = new Josepfu.ListNode(3, null);
        Josepfu.ListNode node4 = new Josepfu.ListNode(4, null);
        Josepfu.ListNode node5 = new Josepfu.ListNode(5, null);

        linkList.add(node1);
        linkList.add(node2);
        linkList.add(node3);
        linkList.add(node4);
        linkList.add(node5);
        return linkList;
    }

    @Test
    public void testCircleLinkList() {
        Josepfu.CircleLinkList linkList = prepareData();
        linkList.printList();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值