回溯法求解陣列中和為固定值的所有元素集合
阿新 • • 發佈:2019-01-08
一、前言
本文參考自http://blog.csdn.net/u012462822/article/details/51193689,找出陣列中和為固定值的所有元素集合,常用的思路是先進行排序,之後再用回溯的方法不斷嘗試所有可能集合。以下先用快速排序(寫得有點爛)降序,再找出降了序的陣列中和為某值的所有元素集合
二、回溯法
程式碼如下
#include <iostream> #include <stdio.h> #include <vector> using namespace std; void QSort(int * arr,int idxStart,int idxEnd) { if (idxEnd<1||arr == NULL) return; int key = arr[idxStart]; int i = idxStart ; int j = idxEnd; while(j != i){ while(j != i){ if(arr[j]>key){ int temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; i++; break; }else{ j--; } } while(j != i){ if( arr[i] <=key){ int temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; j--; break; }else{ i++; } } } if(i > 1){ QSort(arr,0,i-1); } if(idxEnd-i > 1){ QSort(arr,i+1,idxEnd); } } /* arr: 陣列指標 n: 陣列長度 beginIdx: 表示搜尋的位置,初始為0 currSums:存貯搜尋元素的和,初始為0 findT:固定值 res:儲存搜尋的元素 */ void BackTrack( int* arr , int n , int beginIdx , int currSums , int findT , vector< int > & res ) { if ( beginIdx >= n || currSums > findT ) return; //判斷搜尋是否該結束 currSums +=arr[ beginIdx ] ; //加入下標為beginIdx的元素 res.push_back( arr[ beginIdx ] ); if( currSums == findT){ //判斷當前搜尋到的元素是否滿足和為findT,滿足則輸出集合 for(int i = 0 ; i < res.size(); ++i) cout<< res[i] <<" "; cout<<"\n"; } BackTrack( arr , n , beginIdx+1 , currSums , findT , res ) ; //嘗試找下一個 res .pop_back(); //如果BackTrack發生return,說明如果加入beginIdx處的元素不滿足要求 currSums -=arr[ beginIdx ] ; int j ; for( j = beginIdx+1 ; j < n ; ){ //跳過beginIdx之後可能相同的元素 if( arr[j] ==arr[ beginIdx ] ){ j++; }else{ break; } } BackTrack( arr , n , j , currSums , findT , res); //在J後重新搜尋 } int main() { int arr[] = { 6 , 202 , 88, -102 , 100 , 41, 12 , 23 , 34 , 25 , 50, 41 , 11 }; int n = 13 ; QSort( arr , 0 , n -1 ); cout<<"排序後\n"; for(int i = 0 ; i < n ; ++i){ cout<< arr[i] << " " ; } vector< int > path ; int findT = 100; int beginIdx = 0; int currSums = 0; cout<<"\n\n和為" <<findT<<"的元素集合為:\n"; BackTrack( arr , n , beginIdx , currSums , findT , path ) ; }
三、執行結果