1. 程式人生 > >演算法45--回溯法2--Permutations,Permutations2

演算法45--回溯法2--Permutations,Permutations2

Given a collection of distinct integers, return all possible permutations.

Example:

Input: [1,2,3]
Output:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

利用回溯法來解決,考慮每一位可能出現的數字  第一位是nums所有元素都有可能,第二位是除去第一位的所有元素,用r來儲存一個臨時結果,依次考慮r的每一位,每一位都要從nums所有元素進行遍歷,當r中已有該元素時,則跳過進行下一個元素的遍歷,當len(r)==len(nums)時,將此時的r儲存到rr中,刪除r的最後一個元素,進行最後一個元素的下一種可能的遍歷。

class Solution:
    def permute(self, nums=[1,2,3]):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        rr = []
        nums.sort()
        self.backtrace(rr, [], nums)
        return rr
    
    def backtrace(self, rr, r, nums):
        if len(r)==len(nums):
            rr.append(r.copy())
            return
        for i in range(0, len(nums)):
            if nums[i] in r:
                continue
            r.append(nums[i])
            self.backtrace(rr, r, nums)
            r.pop(-1)

全排列的遞迴解法:

def swap(num, i, j):
    tmp = num[i]
    num[i] = num[j]
    num[j] = tmp
 
#num無重複數字 
def fullSort(num, index):
    if index==len(num)-1:
        print (num)
        return
    for i in range(index, len(num)):
        swap(num, index, i)
        fullSort(num, index+1)
        swap(num, index, i)

全排列的非遞迴解法:  依次產生比上一個數大的排列,直到達到最大值

#尋找比替換點大的最小數,倒序尋找,第一個大的數就是目標值 
def findBiggerThanReplaceNum(num, r):
    min = r
    for i in range(len(num)-1, r, -1):
        if num[i]>num[r]:
            return i
    return min
    
def reverse(num, i, j):
    while i<j:
        swap(num, i, j)
        i += 1
        j -= 1
        
def fullSort3(num):
    num.sort()
    print (num)
    #替換數的下標 排序完成後第一個數
    r = len(num)-1
    #替換點的下一個數座標
    m = r
    while r>0:
        m = r    
        r -= 1
        #print ('r = ', r)
        if num[r]<num[m]:
            s = findBiggerThanReplaceNum(num, r)
            #print ('s = ',s)
            swap(num, r, s)
            reverse(num, r+1, len(num)-1)
            print (num)
            #break
            r = len(num)-1

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

Example:

Input: [1,1,2]
Output:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

求出去重的全排列:

回溯法   依次考慮每一位的取值情況,利用flag陣列來儲存nums的每一位是否使用過,第i位數字可以跳過的條件是第i位已經使用,或者nums[i]==nums[i-1]並且第i-1位使用過

class Solution:
    def permuteUnique(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        rr = []
        flag = [False for v in range(len(nums))]
        nums.sort()
        self.backtrace(rr, [], flag, nums)
        return rr
    
    def backtrace(self, rr, r, flag, nums):
        if len(r)==len(nums):
            rr.append(r.copy())
            return
        for i in range(0, len(nums)):
            if flag[i] or i>0 and nums[i-1]==nums[i] and flag[i-1]:
                continue
            r.append(nums[i])
            flag[i] = True
            print(r)
            self.backtrace(rr, r, flag, nums)
            r.pop(-1)
            flag[i] = False

遞迴解法去重:

#num中有重複數字      
def fullSort2(num, index):
    if index==len(num)-1:
        print (num)
        return
    for i in range(index, len(num)):
        #print (isSwap(num, index, i))
        if isSwap(num, index, i):
            swap(num, index, i)
            fullSort2(num, index+1)
            swap(num, index, i)

def isSwap(num, index, i):
    for j in range(index, i):
        if num[j]==num[i]:
            return False
    return True

相關推薦

演算法45--回溯2--PermutationsPermutations2

Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,

【資料結構與演算法回溯解決N皇后問題java程式碼實現

N皇后問題 問題描述 在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法,這稱為八皇后問題。 延伸一下,便為N皇后問題。 核心思想 解決N皇后問題有兩個關鍵點。一是如何進行放置棋子,二是如何驗證棋子是否符合

演算法46--回溯3--Combination Sum1,2,3,4

Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidate

01揹包問題 -- 回溯 2

/*0-1揹包虛擬碼*/ #include <iostream> using namespace std; template<class Typew,class Typep> class Knap //Knap類記錄解空間樹的結點資訊 {

[回溯] 2 四皇后問題

前言 回溯法 1-求n個元素的集合的冪集中狀態變化樹是一棵滿二叉樹:樹中每個葉子結點的狀態都是求解過程中可能出現的狀態(即問題的解)。 【然而】很多問題用回溯和試探求解時,描述求解過程的狀態樹不是一棵滿的多叉樹 【非滿多叉樹】不是滿的多叉樹:當試探過程中出現的狀態和問題所求解產生

【資料結構與演算法回溯解決裝載問題

回溯法解決裝載問題(約束函式優化) 解題思想 遍歷各元素,若cw+w[t]<=c(即船可以裝下),則進入左子樹,w[t]標記為1,再進行遞迴,若cw+r>bestw(即當前節點的右子樹包含最優解的可能),則進入右子樹,否則,則不遍歷右子樹。 完整程式碼實現如下 p

【基礎演算法回溯與八皇后問題

#include"iostream" #include"stdlib.h" using namespace std; int x[8],tot=0; bool B(int x[],int k) { int i; for(i=0;i<k;i++) if(x[i]==x[

演算法入門——回溯

用淺顯的話說回溯法就是屢敗屢戰的一種精神:用走迷宮來說吧,第一次每次遇到岔路就往左走,直到走到死路就回到上一個岔路,這時候不往左了,改為往右,然後繼續一直往左走。差不多就是這樣,但是怕繞,拿過一個比喻吧:比如我要猜出你的6位數支付密碼:一開始我用000000,沒用的話我就回到5位數的時候0000

常用演算法回溯

思路:在包含問題的解空間中,按照深度優先搜尋的策略,從根節點出發深度探索解空間樹,當探索到某一節點時,先判斷該節點是否包含問題的解,如果包含,就從該節點觸發繼續探索下去,如果不包含該節點的解,則逐層向其祖先節點回溯。 示例 組合總和:給定一個無重複元素的陣列 candidates 和一個目標數 targe

常用演算法:分治演算法、動態規劃演算法、貪心演算法回溯、分支限界

1、概念     回溯演算法實際上一個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就“回溯”返回,嘗試別的路徑。    回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再

數獨求解演算法回溯和唯一解法)java實現

數獨(すうどく,Sudoku)是一種運用紙、筆進行演算的邏輯遊戲。玩家需要根據9×9盤面上的已知數字,推理出所有剩餘空格的數字,並滿足每一行、每一列、每一個粗線宮內的數字均含1-9,不重複。     注:數獨的各種知識和解決思路請 參考http://www.llang

[回溯演算法] 五大常用演算法回溯

演算法入門6:回溯法一. 回溯法 – 深度優先搜素                       1. 簡單概述       回溯法思路的簡單描述是:把問題的解空間轉化成了圖或者樹的結構表示,然後使用深度優先搜尋策略進行遍歷,遍歷的過程中記錄和尋找所有可行解或者最優解。基本思想

演算法44--回溯1--subsets,subsets2

1.Subsets Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solution set must not contain d

演算法47--回溯4--演算法總結

之前用回溯法解決了子集,排列,組合等問題,現在總結一下回溯演算法: 在包含問題的所有解的解空間樹中,按照深度優先搜尋的策略,從根結點出發深度探索解空間樹。當探索到某一結點時,要先判斷該結點是否包含問題的解,如果包含,就從該結點出發繼續探索下去,如果該結點不包含問題的解,則逐

演算法回溯四步走

# 回溯法 對於回溯法,網上有很多種解釋,這裡我依照自己的(死宅)觀點做了以下三種通俗易懂的解釋: - **正經版解釋:**其實人生就像一顆充滿了分支的n叉樹,你的每一個選擇都會使你走向不同的路線,獲得不同的結局。如果能重來,我要選李白~呸!說錯了,如果能重來,我們就能回溯到以前,選擇到最美好的結局。 -

(待解決效率低下)47. Permutations II C++回溯

limit gin == ++ 查找 != mys backtrack mit 思路是在相似題Permutations的基礎上,將結果放到set中,利用set容器不會出現重復元素的特性,得到所需結果 但是利用代碼中的/* */部分通過叠代器遍歷set將set中的元素放在一個

資料結構與演算法- 五大常用演算法總結(分治法回溯分治限界貪心演算法動態規劃法)

1.分治法(Recurrence and Divide-Conquer)        對於一個規模為n的問題,若該問題可以容易解決(比如說規模n較小)則直接解決,否則將其分解為k個規模較小的子問題,這些子問題互相獨立且與原問題形式相同,遞迴地解決這些子問

基礎練習 2n皇后問題 ——回溯貪心演算法

/*基礎練習 2n皇后問題問題描述  給定一個n*n的棋盤,棋盤中有一些位置不能放皇后。現在要向棋盤中放入n個黑皇后和n個白皇后,使任意的兩個黑皇后都不在同一行、同一列或同一條對角線上,任意的兩個白皇后都不在同一行、同一列或同一條對角線上。問總共有多少种放法?n小於等於8。輸

求{123}的子集————回溯(遞迴與非遞迴)

求ar[]={1,2,3}的子集序列,小夥伴們可以先自己嘗試解一下~~ #include<iostream> using namespace std; //用回溯法搜尋子集樹 void fun(int *ar,int *br,int n)//非遞迴

一個臺階總共有n 級如果一次可以跳1 級也可以跳2求總共有多少總跳並分析演算法的時間複雜度。

這是華哥那天問我的,當時不想動腦。回來後,網上看了一下,原理很簡單,用到了遞迴。但我遞迴很菜。。。 他的思路是: 我們把n 級臺階時的跳法看成是n 的函式,記為f(n)。當n>2 時,第一次跳的時候就有兩種不同的選擇:一是第一次只跳1 級,此時跳法數目等於後面剩下的n