圓圈中最後剩下數字

題目描述:

0, 1, …, n-1這n個數字(n>0)排成一個圓圈,從數字0開始每次從這個圓圈裏刪除第m個數字。求出這個圓圈裏剩下的最後一個數字。

樣例:

輸入:n=5 , m=3
輸出:3

分析:

將這n個數字存入列表中,通過舉例可以得出第一次刪除的數字下標爲(m-1)%n記爲c,
之後每一次刪除的數字下標均爲(c+m-1)%list.size()

public int LastRemaining_Solution(int n, int m) {
		if(n==0||m==0)
			return -1;
        List<Integer> list=new ArrayList<>();
        for(int i=0;i<n;i++)
        	list.add(i);
        int c=(m-1)%n;
        while(list.size()!=1) {
        	list.remove(c);
        	c=(c+m-1)%list.size();  
        }
        return list.get(0);
    }

環形單鏈表的約瑟夫問題

題目描述

一個環形單向鏈表的頭結點head和報數的值m。
返回:最後生存下來的節點,且這個節點自己組成環形單向鏈表,其他節點都刪掉。

題解

普通解法:

  • 1、如果鏈表爲空或者鏈表節點數爲1,或者m的值小於1,則不用調整就直接返回
  • 2、在環形鏈表中遍歷每個節點,不斷轉圈,不斷讓每個節點報數。
  • 3、當報數達到m時,就刪除當前報數的節點
  • 4、刪除節點後,別忘了還要把剩下的節點繼續連成環狀,繼續轉圈報數,繼續刪除
  • 5、不停地刪除,直到環形鏈表中只剩一個節點,過程結束。
  • 6、每刪除一個節點,都需要遍歷m次,一共需要刪除的節點數爲n-1,所以這種方法的時間複雜度爲O(nm)
public static Node killNode(Node head,int m) {
		if(head==null||head.next==head||m<1) {
			return head;
		}
		Node last=head;
		//找到next節點指向頭結點的節點
		while(last.next!=head) {
			last=last.next;
		}
		int count=0;
		//當next節點指向自己時結束
		while(head!=last) {
			if(++count==m) {
				last.next=head.next;
				count=0;
			}else {
				last=last.next;
			}
			head=last.next;
		}
		return head;
	}

O(N)的解法

  • 1、統計鏈表中節點的個數,將每個節點添加到列表中保存
  • 2、第一次刪除的節點下標爲(m-1)%節點個數
  • 3、下一次刪除的節點下標爲(上一次刪除的節點的下標+m-1)%當前節點個數
  • 4、直到列表長度爲1時停止
public static Node killNode1(Node head,int m) {
		if(head==null||head.next==head||m<1) {
			return head;
		}
		List<Node> list=new ArrayList();
		Node last=head;
		list.add(head);
		//找到next節點指向頭結點的節點
		while(last.next!=head) {
			last=last.next;
			list.add(last);
		}
		int index=(m-1)%list.size();
		while(list.size()!=1) {
			list.remove(index);
			index=(index+m-1)%list.size();
		}
		Node n=list.get(0);
		n.next=n;
		return n;
	}
發佈了124 篇原創文章 · 獲贊 11 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章