说明,本文全文代码均用dart语言实现。

  求一个集合S中m个元素的所有排列情况,并打印,非常适合用递归的思路实现。本文给出了两种实现方法,一种是给定的填充排列数组长度是固定的,一种是可变长度的。两种方法主要思路是一样的,只是实现细节上略有差异。具体代码如下:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
 1 void permute<E>(Set<E> s, int m) {  2   if (m < 0 || m > s.length) throw StateError('m is not in [0, ${s.length}]');  3 
 4   _fill(<E>[], s, m);  5   print('-------------------');  6   _fillFixed(List<E>(m), s, 0, m);  7 }  8 
 9 10 
11 void _fill<E>(List<E> pm, Set<E> s, int m) { 12   if (pm.length < m) { 13     for (var e in s) { 14  pm.add(e); 15  _fill(pm, _rest(s, e), m); 16  } 17   } else { 18  print(pm); 19  } 20   if (pm.isNotEmpty) pm.removeLast(); 21 } 22 
23 void _fillFixed<E>(List<E> pm, Set<E> s, int i, int m) { 24   if (i < m) { 25     for (var e in s) { 26       pm[i] = e; 27       _fillFixed(pm, _rest(s, e), i + 1, m); 28  } 29   } else { 30  print(pm); 31  } 32 } 33 
34 Set _rest<E>(Set<E> s, E e) { 35   var t = s.toSet(); 36  t.remove(e); 37   return t; 38 }

 

  如果求一个集合的全排列,如果是集合的话,其实在上面的函数permute,将m的值设为集合s的长度即可:

1 void permuteAll2<E>(Set<E> s) => permute(s, s.length);

  如果求一个数组的全排列情况(假设数组中元素不重合),可以不像集合那样,还需要额外申请空间,直接利用数组本身即可完成:

 1 void permuteAll(List a, int k) {  2   if (k < a.length - 1) {  3     for (int i = k; i < a.length; i++) {  4       if (i != k) _swap(a, k, i);  5       permuteAll(a, k + 1);  6       if (i != k) _swap(a, k, i);  7  }  8   } else {  9  print(a); 10  } 11 } 12 
13 void _swap(List a, int i, int j) { 14   var t = a[i]; 15   a[i] = a[j]; 16   a[j] = t; 17 }

  具体思路,比较简单,直接查看代码即可,或者参照网上的讲解,这里不再赘述了。有兴趣的也可以直接debug,可以看每一步的操作。

  最后,验证代码如下:

1 void main() { 2   var s = {1, 2, 3}; 3   permute(s, 3); 4   print('---------------------\n'); 5   permuteAll(s.toList(), 0); 6   print('---------------------\n'); 7  permuteAll2(s); 8 }

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄