人工神经网络的应用系统中的激活函数排列组合,出现问题怎么办

人工神经网络复习题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
人工神经网络复习题
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩10页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢1-人工神经网络-BP_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
1-人工神经网络-BP
上传于||暂无简介
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩29页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢数据结构与算法(16)
排列组合通常用于在字符串或序列的排列和组合中,其特点是固定的解法和统一的代码风格。通常有两种方法:第一种是类似动态规划的分期摊还的方式,即保存中间结果,依次附上新元素,产生新的中间结果;第二种是递归法,通常是在递归函数里,使用for循环,遍历所有排列或组合的可能,然后在for循环语句内调用递归函数。
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来
,换一条路再试。用回溯算法解决问题的一般步骤为:
1、定义一个解空间,它包含问题的解。
2、利用适于搜索的方法组织解空间。
3、利用深度优先法搜索解空间。
4、利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
对于长度为n的数组,我们需要依次确认每个位置上的元素。初始问题:从a[0]开始依次确认n个元素。如果我们确认a[0]之后,问题就变成从a[1]开始从剩余元素中选择一个元素确定a[1]。每次选择都有多种可能性,我们依次尝试(尝试后还原),并递归解决选择之后的产生的子问题,并定义出口。&
public List&List&Integer&& permute(int[] nums) {
ArrayList&Integer& numsArray=new ArrayList&Integer&();
for(int i:nums){
numsArray.add(i);
Collections.sort(numsArray);
List&List&Integer&& res=new ArrayList&List&Integer&&();
solve(res,numsArray,0);
private void solve(List&List&Integer&& res,ArrayList&Integer& nums,int index){
if(index&=nums.size()){
List&Integer& permutation=new ArrayList&Integer&(nums);
res.add(permutation);
for(int i=i&=nums.size()-1;i++){
Collections.swap(nums, i, index);
solve(res,nums,index+1);
Collections.swap(nums, i, index);
用一个标记数组标记元素是否已经使用过,每次从剩余元素中尝试添加新元素到临时解中,当没有新的元素可添加时,临时解就为最终的一个解。此方案比方法一要更加直观。
public List&List&Integer&& permute(int[] nums) {
ArrayList&Integer& numsArray=new ArrayList&Integer&();
for(int i:nums){
numsArray.add(i);
boolean[] used=new boolean[numsArray.size()];
Collections.sort(numsArray);
List&List&Integer&& res=new ArrayList&List&Integer&&();
ArrayList&Integer& subSet=new ArrayList&Integer&();
solve(res,numsArray,subSet,used);
private void solve(List&List&Integer&& res,ArrayList&Integer& nums,ArrayList&Integer& subSet,boolean[] used){
if(subSet.size()==nums.size()){
ArrayList&Integer& clone=new ArrayList&Integer&(subSet);
res.add(clone);
for(int i=0;i&nums.size();i++){
if(used[i])//不能重复使用
subSet.add(nums.get(i));//加入新元素,并递归调用下一个元素
solve(res,nums,subSet,used);
subSet.remove(subSet.size()-1);//还原
相比上一个问题,元素可以重复,因此我们应该在算法中增加相应的判断来避免重复结果。例如元素[1,2,2,3,3,3],在选择添加第一个新元素时,只考虑第一个1,第一个2,第一个3。注:仔细理清楚避免重复的逻辑,后面会多次用到。
public List&List&Integer&& permuteUnique(int[] nums) {
ArrayList&Integer& numsArray=new ArrayList&Integer&();
for(int i:nums){
numsArray.add(i);
boolean[] used=new boolean[numsArray.size()];
Collections.sort(numsArray);
List&List&Integer&& res=new ArrayList&List&Integer&&();
ArrayList&Integer& subSet=new ArrayList&Integer&();
solve(res,numsArray,subSet,used);
private void solve(List&List&Integer&& res,ArrayList&Integer& nums,ArrayList&Integer& subSet,boolean[] used){
if(subSet.size()==nums.size()){
ArrayList&Integer& clone=new ArrayList&Integer&(subSet);
res.add(clone);
for(int i=0;i&nums.size();i++){
//对于剩余可选元素,那些相同的元素,我们只考虑第一个
//如果前一个元素与当前元素相同,且前一个元素已经使用了(之前的选择),说明当前元素是“剩余可选元素中所有与当前元素相同的元素”的第一个,则可以选择
//如果前一个元素与当前元素相同,但是前一个元素没有使用,说明在此次选择过程中,已经有相同的元素尝试选择过然后还原了,因此将当前元素忽略
if(used[i]||(i&0&&!used[i-1]&&nums.get(i).equals(nums.get(i-1))))
subSet.add(nums.get(i));//加入新元素,并递归调用下一个元素
solve(res,nums,subSet,used);
subSet.remove(subSet.size()-1);//还原
我们将排列看成一个n位整数,下一个排列组合就是当前整数增加并且保证增量最小。为了保证增量最小,因此我们需要保证变化的范围尽量限制在低位。因此我们采用如下策略:
1、从后往前寻找第一组相邻元素a[i]&a[i+1]。如果没找到,说明当前序列递减(最大整数),下一个排列只需将序列逆转成最小。如果找到,执行2.
2、为了让变化范围最小化,我们需要将a[i]后面“大于a[i]且最接近a[i]的元素”与a[i]交换,交换后的a[i]后面依然是递减序列,为了进一步减小增量,我们将a[i]后面的元素逆序,得到如下算法。
public void nextPermutation(int[] nums) {
int index=nums.length-1;
//寻找第一对非递减序列
while(index-1&=0&&nums[index-1]&=nums[index]) index--;
if(index==0){
reverse(nums,0,nums.length-1);
int smallerIndex=index-1,change=
//寻找恰当交换元素
while(change+1&nums.length&&nums[change+1]&nums[smallerIndex])change++;
int t=nums[smallerIndex];nums[smallerIndex]=nums[change];nums[change]=t;
reverse(nums,index,nums.length-1);
private void reverse(int[] nums,int begin,int end){
while(begin&end){
t=nums[begin];nums[begin]=nums[end];nums[end]=t;
begin++;end--;
方案一:我们可以采用暴力枚举,调用k-1次nextPermutation。我们只需要第k个排列,但是我们却计算了前k个,比较耗时。
方案二:n个不同元素的排列种数位n!,我们将[1,2,3,4,5]变换成[2,1,3,4,5]需要多少次变换呢?答案是4!次。
证明:[1,2,3,4,5]变换成[1,5,4,3,2]需要4!-1次,[1,5,4,3,2]变换成[2,1,3,4,5]需要一次,共4!次。
同理:[2,1,3,4,5]变换成[2,3,1,4,5]需要经过3!次变换。
综上所述:将a[i]与“其后大于a[i]且最接近a[i]的元素”进行交换,即代表(n-i)!,1&=i&=n(在这里下标从1开始)次变换。
因此第k个排列,即为初始排列变换k-1次。得到如下算法
public String getPermutation(int n, int k) {
int[] arr=new int[n+1];
for(int i=1;i&=n;i++){
k=(k-1)%factorial(n);
int index=1;
while(k&0){
if(k&=factorial(n-index)){
int change=index+1;
while(arr[change]&arr[index])change++;
int t=arr[index];arr[index]=arr[change];arr[change]=t;
k-=factorial(n-index);
StringBuilder res=new StringBuilder();
for(int i=1;i&=n;i++){
res.append(arr[i]);
return res.toString();
private int factorial(int n){
int res=1;
for(int i=1;i&=n;i++){
我们采用分期摊还的方法,从数字字符串的第一个字符开始扫描,记录之前数字产生的所有组合,然后将当前数字映射的字符附加到之前产生的所有组合中,产生新的结果集。
public List&String& letterCombinations(String digits) {
String[] strMap={&&,&&,&abc&,&def&,&ghi&,&jkl&,&mno&,&pqrs&,&tuv&,&wxyz&};
ArrayList&String& res=new ArrayList&String&();
if(digits.equals(&&)||digits==null)
res.add(&&);
for(int i=0;i&digits.length();i++){
String map=strMap[digits.charAt(i)-'0'];
if(map.equals(&&)){
ArrayList&String& t=new ArrayList&String&();
for(int j=0;j&map.length();j++){
for(String str:res){
t.add(str+map.charAt(j));
类似全排列,采用分期摊还方法,不过需要注意过滤重复组合。
public List&List&Integer&& combine(int n, int k) {
List&List&Integer&& res=new ArrayList&List&Integer&&();
int[] nums=new int[n];
ArrayList&Integer& r=new ArrayList&Integer&();
boolean[] used=new boolean[n];
for(int i=0;i&n;i++)
nums[i]=i+1;
solve(res,r,nums,k,used);
public void solve(List&List&Integer&& res,ArrayList&Integer& r,int[] nums,int k,boolean[] used){
if(r.size()==k){
ArrayList&Integer& clone=new ArrayList&Integer&(r);
res.add(clone);
int index=r.size();
for(int i=i&nums.i++){
if(used[i]||(r.size()!=0&&nums[i]&r.get(r.size()-1)))
r.add(nums[i]);
solve(res,r,nums,k,used);
r.remove(r.size()-1);
先将候选数组排序,我们将问题理解为从a[0]开始选择整数,使得和为target。如果我们选择了a[0],那么问题变换成从a[0]开始选择整数,使得和为target-a[0](因为可以重复选择)。如果没有选择a[0],那么问题变换为从a[1]开始选择整数,使得和为target。因此得到如下递归解法:
public List&List&Integer&& combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List&List&Integer&& res=new ArrayList&List&Integer&&();
ArrayList&Integer& r=new ArrayList&Integer&();
solve(res,r,candidates,target,0);
public void solve(List&List&Integer&& res,ArrayList&Integer& r,int[] candidates,int target,int index){
if(target==0){
ArrayList&Integer& clone=new ArrayList&Integer&(r);
res.add(clone);
if(index&=candidates.length||target&candidates[index])
//选择当前元素
r.add(candidates[index]);
solve(res, r, candidates, target-candidates[index], index);
r.remove(r.size()-1);
//不选择当前元素
solve(res, r, candidates, target, index+1);
public List&List&Integer&& combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List&List&Integer&& res=new ArrayList&List&Integer&&();
ArrayList&Integer& r=new ArrayList&Integer&();
solve(res,r,candidates,target,0);
public void solve(List&List&Integer&& res,ArrayList&Integer& r,int[] candidates,int target,int index){
if(target==0){
ArrayList&Integer& clone=new ArrayList&Integer&(r);
res.add(clone);
if(index&=candidates.length||target&candidates[index])
//选择当前元素
r.add(candidates[index]);
solve(res, r, candidates, target-candidates[index], index+1);
r.remove(r.size()-1);
//不选择当前元素
int nextIndex=index+1;
while(nextIndex&candidates.length&&candidates[nextIndex]==candidates[index])nextIndex++;
solve(res, r, candidates, target, nextIndex);
public List&List&Integer&& combinationSum3(int k, int n) {
List&List&Integer&& res=new ArrayList&List&Integer&&();
ArrayList&Integer& sub=new ArrayList&Integer&();
solve(res,sub,k,n,1);
private void solve(List&List&Integer&& res,ArrayList&Integer& sub,int k,int n,int start){
if(sub.size()==k&&n==0){
ArrayList&Integer& clone=new ArrayList&Integer&(sub);
res.add(clone);
if(n&0||start==10||(sub.size()==k&&n!=0)){
//选择当前元素
sub.add(start);
solve(res,sub,k,n-start,start+1);
sub.remove(sub.size()-1);
//不选择当前元素
solve(res,sub,k,n,start+1);
对于合法的括号表达式,从左边往右边看时,每时每刻左括号的个数大于等于右括号的个数。
我们可以将问题看成是对于长为2 n的字符串,从第一个位置开始我们选择'('或者')',同时要保证左括号个数永远大于右边括号的个数,并且最终左括号和右括号的个数都等于n。当我们做完所有的选择就得到了合法的括号表达式。
因此得到如下递归解法:
public List&String& generateParenthesis(int n) {
List&String& res=new ArrayList&String&();
res.add(&&);
StringBuilder r=new StringBuilder();
solve(n,0,0,res,r);
private void solve(int n,int left,int right,List&String& res,StringBuilder r){
if(r.length()==2*n){
System.out.println(r.toString());
res.add(r.toString());
if(left&right)
if(left&n){
//添加左边括号
r.append(&(&);
solve(n,left+1,right,res,r);
r.setLength(r.length() - 1);
//添加右边括号
r.append(&)&);
solve(n,left,right+1,res,r);
r.setLength(r.length() - 1);
采用分期摊还的方法。
public List&List&Integer&& subsets(int[] nums) {
List&List&Integer&& res=new ArrayList&List&Integer&&();
res.add(new ArrayList&Integer&());
for(int i=0;i&nums.i++){
List&List&Integer&& t=new ArrayList&List&Integer&&();
for(List&Integer& r:res){
ArrayList&Integer& clone=new ArrayList&Integer&(r);
clone.add(nums[i]);
t.add(clone);
因为元素可以重复,并且需要过滤重复的集合,我们需要对生成子集的过程进行进一步的控制。我们将问题理解为,从a[0]开始求所有的子集,该问题可以分为两个问题1、选择a[0],从a[1]开始求所有子集并对每个子集加上a[0];2从a[1]开始求所有的子集。因此得到如下递归解法。
注:由于需要消除重复子集,因此我们在选择当前元素a[i]时,如果a[i-1]等于a[i]且我们没有选择,我们就必定不能选择a[i]。
public List&List&Integer&& subsetsWithDup(int[] nums) {
Arrays.sort(nums);
boolean[] used=new boolean[nums.length];
List&List&Integer&& res=new ArrayList&List&Integer&&();
ArrayList&Integer& sub=new ArrayList&Integer&();
solve(res,0,sub,nums,used);
private void solve(List&List&Integer&& res,int start,ArrayList&Integer& sub,int[] nums,boolean[] used){
if(start==nums.length){
ArrayList&Integer& clone=new ArrayList&Integer&(sub);
res.add(clone);
//选择当前元素
if(start&0&&nums[start]==nums[start-1]&&!used[start-1]){
//do nothing
used[start]=
sub.add(nums[start]);
solve(res,start+1,sub,nums,used);
sub.remove(sub.size()-1);
used[start]=
//不选择当前元素
solve(res,start+1,sub,nums,used);
我们从每一个位置开始回溯,并标记元素是否已经使用过。
public boolean exist(char[][] board, String word) {
boolean used[][]=new boolean[board.length][board[0].length];
for(int i=0;i&board.i++){
for(int j=0;j&board[0].j++){
if(solve(board,word,i,j,used,0))
public boolean solve(char[][] board,String word,int row,int col,boolean[][] used,int start){
if(start==word.length()){
if(row&0||col&0||row==board.length||col==board[0].length){
if(board[row][col]!=word.charAt(start)||used[row][col]){
if(used[row][col]){
used[row][col]=
boolean mark=
mark=mark||solve(board,word,row+1,col,used,start+1);
mark=mark||solve(board,word,row-1,col,used,start+1);
mark=mark||solve(board,word,row,col+1,used,start+1);
mark=mark||solve(board,word,row,col-1,used,start+1);
used[row][col]=
思考:如果我们有很多的单词需要查找时,如何避免重复的搜索过程呢?我们可以先建立trie树(单词查找树),然后对trie中的不同路径进行搜索。见leetcode 212&
对于每一个字符,我们首先找到以该字符为首的回文字符串,然后我们依次其中的回文传,并递归求解选择后的问题。
public List&List&String&& partition(String s) {
List&List&String&& res=new ArrayList&List&String&&();
List&String& sub=new ArrayList&String&();
solve(res,sub,s,0);
private void solve(List&List&String&& res,List&String& sub,String s,int start){
if(start==s.length()){
List&String& clone=new ArrayList&String&(sub);
res.add(clone);
List&Integer& ends=new ArrayList&Integer&();
for(int i=i&s.length();i++){
if(isPalindrome(s,start,i)){
ends.add(i);
for(int end:ends){
sub.add(s.substring(start, end+1));
solve(res,sub,s,end+1);
sub.remove(sub.size()-1);
private boolean isPalindrome(String s,int start,int end){
while(start&=end){
if(s.charAt(start)!=s.charAt(end)){
start++;end--;
对于每个待填的空位我们可以尝试1-9所有可能性,如果解决了问题就直接结束。如果所有尝试都没能解决问题,就需要调整之前已经确认的空位,回溯到调整上一个空位的值。因此,此处调用子问题时必须返回是否能够解决问题的转态,以便回溯。
public void solveSudoku(char[][] board) {
ArrayList&ArrayList&Integer&& emptyLocations=
new ArrayList&ArrayList&Integer&&();
for(int row=0;row&9;row++){
for(int col=0;col&9;col++){
if(board[row][col]=='.'){
ArrayList&Integer& location=new ArrayList&Integer&();
location.add(row);location.add(col);
emptyLocations.add(location);
solve(board,0,emptyLocations);
private boolean solve(char[][] board,int index,ArrayList&ArrayList&Integer&& emptyLocations){
if(index==emptyLocations.size()){
ArrayList&Integer& location=emptyLocations.get(index);
int row=location.get(0),col=location.get(1);
for(char c='1';c&='9';c++){
if(isValid(board,row,col,c)){
board[row][col]=c;
if(solve(board,index+1,emptyLocations)){
board[row][col]='.';
public boolean isValid(char[][] board,int row,int col,char c){
for(int i=0;i&9;i++){
if(board[row][i]==c)
for(int i=0;i&9;i++){
if(board[i][col]==c)
//验证3*3格子
for(int i=(row/3)*3;i&(row/3)*3+3;i++){
for(int j=(col/3)*3;j&(col/3)*3+3;j++){
if(board[i][j]==c)
我们知道N皇后问题通常采用回溯法求解。
对于每行每个位置进行尝试,并判断是否合法。
public List&List&String&& solveNQueens(int n) {
ArrayList&Integer& locations=new ArrayList&Integer&();
List&List&String&& res=new ArrayList&List&String&&();
solve(res,locations,n);
private void solve(List&List&String&& res,ArrayList&Integer& locations,int n){
if(n==locations.size()){
addRes(res,locations);
for(int i=0;i&n;i++){
if(isValid(locations,i)){
locations.add(i);
solve(res,locations,n);
locations.remove(locations.size()-1);
private boolean isValid(ArrayList&Integer& locations,int location){
for(int i=0;i&locations.size();i++){
if(location-locations.get(i)==locations.size()-i||
location-locations.get(i)==i-locations.size())
if(location==locations.get(i))
private void addRes(List&List&String&& res,ArrayList&Integer& locations){
List&String& r=new ArrayList&String&();
for(int i=0;i&locations.size();i++){
StringBuilder builder=new StringBuilder();
for(int j=0;j&locations.size();j++){
if(locations.get(i)==j){
builder.append(&Q&);
builder.append(&.&);
r.add(builder.toString());
res.add(r);
我们将每行中皇后的位置用1-N表示,共N行。这1-N的任意排列,即可满足任意两个皇后不在同行或同列,我们只需要对产生的全排列进行验证即可。
public List&List&String&& solveNQueens(int n) {
int[] locations=new int[n+1];
for(int i=1;i&=n;i++){
locations[i]=i;
List&List&String&& res=new ArrayList&List&String&&();
solve(res,locations,1);
private void solve(List&List&String&& res,int[] locations,int index){
if(index==locations.length){
addRes(res,locations);
for(int i=i&=locations.length-1;i++){
if(isValid(locations,index,i)){
int t=locations[index];locations[index]=locations[i];locations[i]=t;
solve(res,locations,index+1);
t=locations[index];locations[index]=locations[i];locations[i]=t;
private boolean isValid(int[] locations,int index,int change){
for(int i=1;i&i++){
if(locations[i]-locations[change]==index-i||
locations[i]-locations[change]==i-index)
private void addRes(List&List&String&& res,int[] locations){
List&String& r=new ArrayList&String&();
for(int i=1;i&=locations.length-1;i++){
StringBuilder builder=new StringBuilder();
for(int j=1;j&=locations.length-1;j++){
if(locations[i]==j){
builder.append(&Q&);
builder.append(&.&);
r.add(builder.toString());
res.add(r);
注:在统计结果数量时,由于Java本身都是按值传递参数的(对于对象传递的是地址值),因此我们不用用int类型统计结果数量,同时由于Integer是不可变的,因此也不能使用Integer。这里我采用Integer容器来统计数量,此外还可以利用AtomicInteger原子整型或自定义引用类型来进行统计,也可以在方法调用中返回结果数量。如有更好的方法忘指教,谢谢!!
public int totalNQueens(int n) {
ArrayList&Integer& locations=new ArrayList&Integer&();
Stack&Integer& count=new Stack&Integer&();
count.add(new Integer(0));
solve(locations,n,count);
return count.get(0);
private void solve(ArrayList&Integer& locations,int n,Stack&Integer& count){
if(n==locations.size()){
count.push(new Integer(count.pop()+1));
for(int i=0;i&n;i++){
if(isValid(locations,i)){
locations.add(i);
solve(locations,n,count);
locations.remove(locations.size()-1);
private boolean isValid(ArrayList&Integer& locations,int location){
for(int i=0;i&locations.size();i++){
if(location-locations.get(i)==locations.size()-i||
location-locations.get(i)==i-locations.size())
if(location==locations.get(i))
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:38122次
积分:1017
积分:1017
排名:千里之外
原创:60篇
评论:14条浅谈公务员考试行测排列组合之隔板问题_行测_中公教育网
浅谈公务员考试行测排列组合之隔板问题
排列组合问题是公务员考试中的重点也是难点,每年的公考几乎都不拉下,出题形式丰富。因为排列组合问题能够多方面考察应试者的逻辑思维能力,因此无论是省考还是国考抑或地方事业单位考试,都备受命题人青睐!做题方法大致可以分为特殊优先法、捆绑法、插空法、间接计数法以及隔板法。尤其是隔板法,由于出题形式灵活多变,往往让许多考生望而却步,正所谓难者不会,会者不难,现在中公教育专家就跟大家对隔板问题进行一下简单的讨论。
更多行测相关高分备考技巧 请参考中公教育
&关注中公教育微信wwwoffcn,政策问题实时答,考试信息不漏看。
(责任编辑:王冰冰)
本文相关热点文章推荐

我要回帖

更多关于 人工神经网络教程 的文章

 

随机推荐