1. 程式人生 > >劍指offer面試題28 字串的全排列

劍指offer面試題28 字串的全排列

有重複全排列解題思路:
整體思路:可以把一個字串看成兩部分組成,第一部分為第一個字元,第二部分是後面的所有字元。這是典型的分治思想,可以用遞迴實現。

具體來說:第一步首先求所有可能出現在第一個位置上的字元,即把第一個字元和後面的所有的字元(包括第一個字元)進行交換。因字串中可能有重複的字元,因此在交換前,需要判斷從當前字串的開始位置start到待交換位置end之前,是否有字元和end指向的字元相等,若有,則不進行交換,等到遞迴到那個字串的時候在進行交換,否則在結果中會出現重複元素。第二步固定第一個字元,求後面所有字元的全排列,過程同上。

import java.util.ArrayList;
import java.util.Collections;

public class Solution {
	
	public static ArrayList<String> Permutation(String str) {
		
		ArrayList<String> arrayList = new ArrayList<>();
		
		if (str == null || str.length() == 0) {
			return arrayList;
		}
		
		char[] charArray = str.toCharArray();
		int start = 0;
		int end = charArray.length - 1;
		arrayList = Permutation(charArray,start,end,arrayList);
		Collections.sort(arrayList);
		return arrayList;
	       
    }
	
	/**
	 * 從start到end-1之間有沒有元素和end指向元素相同,若有,則不進行交換,因為在此之前肯定進行了交換
	 */
	private static boolean isSwap(char[] charArray, int start, int end) {
		
		for (int i = start; i < end; i++) {
			if (charArray[i] == charArray[end]) {
				return false;
			}
		}
		return true;
		
	}

	private static ArrayList<String> Permutation(char[] charArray,int start, int end, ArrayList<String> arrayList) {
		
		if (start == charArray.length - 1) {
			//遞迴地結束條件
			String str = String.valueOf(charArray);
			arrayList.add(str);
			return arrayList;
		}
		
		for (int i = start; i < charArray.length; i++) {
			
			//如果在start到i-1之間,i元素已經出現過,則此時無需交換,因為在此之前已經交換了,避免重複
			if (!isSwap(charArray, start, i)) {
				continue;
			}
			swap(charArray, start, i);
			Permutation(charArray, start + 1, end,arrayList);
			swap(charArray, start, i);
		}
		
		return arrayList;
		
	}

	private static void swap(char[] charArray, int i, int j) {
		
		char temp = charArray[i];
		charArray[i] = charArray[j];
		charArray[j] = temp;
	}
	
	public static void main(String[] args) {
		String s = "abab";
		ArrayList<String> list = Permutation(s);
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}
}


相關推薦

offer--試題28:字串排列--Java實現

題目描述: 輸入一個字串,打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a、b、c所能排列出來的所有字串abc、acb、bac、bca、cab和cba。 解題思路: 我們求整個字串的排列,可以看成兩步,首先求可能出現在第一個位置上的字元,

offer試題28 字串排列

有重複全排列解題思路: 整體思路:可以把一個字串看成兩部分組成,第一部分為第一個字元,第二部分是後面的所有字元。這是典型的分治思想,可以用遞迴實現。具體來說:第一步首先求所有可能出現在第一個位置上的字元,即把第一個字元和後面的所有的字元(包括第一個字元)進行交換。因字串中可

offer 試題28字串排列

題目: 輸入一個字串,按字典序打印出該字串中字元的所有排列。 例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。 結果請按字母順序

offer 試題28:對稱的二叉樹 c++

題目:請實現一個函式,用來判斷一顆二叉樹是不是對稱的。注意,如果一個二叉樹同此二叉樹的映象是同樣的,定義其為對稱的。(要想象一下他的結構) 思路:遞迴判斷,左子樹的左子樹和右子樹的右子樹比較,左子樹的右子樹和右子樹的左子樹比較,若相等則是,否則不是。 class Solution { pub

Offer 試題28 對稱的二叉樹

題目描述 請實現一個函式,用來判斷一顆二叉樹是不是對稱的。注意,如果一個二叉樹同此二叉樹的映象是同樣的,定義其為對稱的。 boolean isSymmetrical(TreeNode pRoot)

offer 試題20:表示數值的字串

請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。例如,字串"+100","5e2","-123","3.1416"和"-1E-16"都表示數值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。 可以用A[.[B]][e|EC]或者.B[e|EC

offer 試題42:左旋轉字串vs翻轉單詞順序 c++

題目:組合語言中有一種移位指令叫做迴圈左移(ROL),現在有個簡單的任務,就是用字串模擬這個指令的運算結果。對於一個給定的字元序列S,請你把其迴圈左移K位後的序列輸出。例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它!

Offer試題28.連續子陣列的最大和

一、題目:連續子陣列的最大和 題目:輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間複雜度為O(n)。例如輸入的陣列為{1,-2,3,10,-4,7,2,-5},和最大的子陣列為{3,10,-4,7,2},因此輸出為該子陣列的和18。

Offer試題:34.翻轉單詞順序VS左旋轉字串

一、題目一:翻轉單詞順序 1.1 題目說明 題目一:輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。為簡單起見,標點符號和普通字母一樣處理。例如輸入字串"I am a student.",則輸出"student. a am I"。 1.2 解題思路   第一步翻轉句子中所有的字

Offer試題:35.將字串轉換為數字

一、題目:將字串轉換為數字 題目:寫一個函式StrToInt,實現把字串轉換成整數這個功能。當然,不能使用atoi或者其他類似的庫函式。 二、程式碼實現   (1)考慮輸入的字串是否是NULL、空字串   (2)考慮輸入的字串是否包含正負號或者是否是隻包含正負號   (3)考慮輸入的字串是否

offer試題49:把字串轉為整數

此題並不複雜,主要是想考做題人思維的嚴密性和程式碼的健壯性,要想寫出完整的正確的程式碼,必須要考慮各種異常的情況,以及設計出足夠多的測試用例以供正確性檢驗,因此可以說也並不簡單,至少剛開始對我來說就是這樣的。 我們主要考慮的是輸入字串引數存在的各種可能性:

offer 試題35擴充套件:從第一個字串中刪除第二個字串中的所有字元 (C++版)

題目描述: 例如,輸入”They are students.”和”aeiou”,則刪除之後的第一個字串變成”Thy r stdnts.”。 思路分析: 總體來說,就是在第一字元中拿到一個字元,判斷其是否在第二個字串中,在的話,就刪除該字元。 考慮如下幾個問題: 1、如何在

C++字串過載運算子函式(offer試題1)

//劍指offer面試題1:過載運算子函式 //題目:如下為型別CMyString的宣告,請為該型別新增多種運算子函式。 #include<iostream> #include<cstring> #include<cstdio>

Offer試題42:翻轉單詞順序;左旋轉字串 Java實現

/************************************************************** * Copyright (c) 2016, * All rights reserved. * 版 本 號:v1.0

Offer試題15(Java版):鏈表中倒數第K個結點

head 計數器 easy sta 相同 ret white style 輸出 題目: 輸入一個鏈表。輸出該鏈表中倒數第k哥結點。 為了符合大多數人的習慣,本題從1開始計數。即鏈表的尾結點是倒數第1個結點。 比如一個鏈表有6個結點。從頭結點開始它們的值依次是1。2。

Offer試題】 九度OJ1516:調整數組順序使奇數位於偶數前面

pen 沒有 name func hide tracking 順序 popu type 題目鏈接地址: http://ac.jobdu.com/problem.php?pid=1516 題目1516:調整數組順序使奇數位於偶數前面 時間限制:

Offer試題43(Java版):n個骰子的點數

pac pos max mod ins pri class pro bili 題目:把n個骰子仍在地上。全部骰子朝上一面的點數之和為s,輸入n,打印出s的全部可能的值出現的概率。 解法一:基於遞歸求骰子的點數,時間效率不夠高 如今我們考慮怎樣統計每個點數出現的次數。要向

offer - 試題33 - 把數組排成最小的數

print offer include .html str 把數組排成最小的數 pri tr1 class #include<iostream> #include<vector> #include<string> #include<

offer試題-Java版-持續更新

紅色 縮小 進行 n-1 bubuko 變量 argument style 對象 最近在用Java刷劍指offer(第二版)的面試題。書中原題的代碼采用C++編寫,有些題的初衷是為了考察C++的指針、模板等特性,這些題使用Java編寫有些不合適。但多數題還是考察通用的算法、

leetcode 70. 爬樓梯【遞迴】【Easy】&& Offer試題10 題目2:青蛙跳臺階問題

題目: 假設你正在爬樓梯。需要 n 階你才能到達樓頂。 每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢? 注意:給定 n 是一個正整數。 示例 1: 輸入: 2 輸出: 2 解釋: 有兩種方法可以爬到樓頂。 1. 1