算法总结之 环形单链表的约瑟夫问题
著名的约瑟夫杀人问题 哈哈哈哈
解读:
输入:一个环型单向链表的头节点head和报数m
返回: 最后生存下来的节点,并且这个节点自己组成环形单向链表,其他的节点都删掉
进阶问题: 如果链表节点数为N,想在时间复杂度为O(N)时完成原问题的要求,咋办?
普通解法:
如果链表为空或者节点数为1 或者m<1 直接返回
在环形链表中遍历每个节点,不断转圈,不断报数
当报数到m时,就删除当前报数的节点
删除节点后把剩下的继续连城环状 继续转圈报数 继续删除
不停删除 直到唤醒链表中只剩下一个节点 介绍~
看代码:
package TT; public class Test91 { public class Node{ public int value; public Node next; public Node(int data){ this.value = data; } } public Node josephusKill(Node head, int m){ if(head==null || head.next==null || m<1){ return head; } Node last=head; while(last.next != head){ last=last.next; } int count=0; while(head != last){ if(++count==m){ last.next=head.next; count=0; }else { last=last.next; } head = last.next; } return head; } }
用集合方案解决:
package com.toov5.test; import java.util.ArrayList; import java.util.List; public class Test9 { public static Integer getLastOne(List<Integer> list,int m) { int count = 1; int index = 0; while(list.size() !=1) { if (count % m == 0) { list.remove(index); System.out.println(list); //结合自己画的图,看看此时指针指向的元素是谁哈 //System.out.println(list.get(index)); } if ( index<list.size()-1) { index++; }else { index=0; } count++; } return list.get(0); } public static void main(String[] args) { List<Integer> list =new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println(getLastOne(list, 3)); } }
注意 list 做for 循环时候
不可以进行操作 调用其api之类的!
ConcurrenModificationException异常,原因是,集合不可以一边遍历一边删除。