1. 程式人生 > >leetcode 46 47 全排列2 Java

leetcode 46 47 全排列2 Java

思路

46題主要是用遞迴的方法,從左到右遍歷陣列,依此將該下標和後面的數字兩兩交換,然後繼續遞迴下去,並用一個變數start記錄當前下標。直到start越過陣列下標(nums.length())時結束。
47題主要是比46題要多一個判斷重複的處理,47題的程式碼中比46題的只多了幾行,比如對2,2,1,1,要確保第一個元素2只和1個2交換,只和1個1交換(注意它和它自己交換也算一次交換)

程式碼如下:

46題

//46 領先98%以上
List<List<Integer>> res = new ArrayList<>();
	public List<List<Integer>> permute(int[] nums) {
		res.clear();
		dfs(nums, 0);//
		return res;
	}
	
	public void dfs(int[] n, int start) {//start表示要被替換元素的位置
		if( start >= n.length) {
			List<Integer> list = new ArrayList<Integer>();
			for(int i : n) {
				list.add(i);
			}
			res.add(list);
			return;
		}
		
		for(int i = start; i< n.length; i++) {//i從start開始,如果從start+1開始的話,會把當前序列遺漏掉直接儲存了下一個序列
			int temp= n[i];
			n[i] = n[start];
			n[start] = temp;
			dfs(n, start + 1);//遞迴下一個位置
			//回到上一個狀態
			n[start] = n[i];
			n[i] = temp;
		}
	}

47題

//47題 領先43%
List<List<Integer>> res = new ArrayList<>();
	public List<List<Integer>> permuteUnique(int[] nums) {
		res.clear();
		dfs2(nums, 0);//
		return res;
    }
	public void dfs2(int[] n, int start) {//start表示要被替換元素的位置
		if( start == n.length) {
			List<Integer> list = new ArrayList<Integer>();
			for(int i=0; i<n.length;i++) {
				list.add(n[i]);
			}
			res.add(list);//有重複元素時
			//可以利用下面這種方式去重,但是速度很慢
//			if( !res.contains(list)) {
//				res.add(list);
//			}
			return;
		}
		
		//如果後面有重複的元素,要確保只和最多1個1交換,最多隻和1個2交換,......
		Set<Integer> set = new HashSet<Integer>();
		for(int i = start; i< n.length; i++) {//i從start開始,如果從start+1開始的話,會把當前序列遺漏掉直接儲存了下一個序列
			if(set.contains(n[i])) {
				continue;
			} 
			
			set.add(n[i]);//如果不包含的話,設定訪問過
			int temp= n[i];
			n[i] = n[start];
			n[start] = temp;
			dfs2(n, start + 1);//遞迴下一個位置
			//回到上一個狀態
			n[start] = n[i];
			n[i] = temp;
		}
	}