递归——单词全排列

本文探讨了如何使用递归实现单词的全排列,详细解释了递归的基本概念和注意事项,并通过实例展示了如何通过递归生成任意长度单词的所有字母组合,同时也讨论了递归效率的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      递归是编程技术中常用的一种技术,就是方法是支持自己调用自己,在面对过程编程中已经有了递归的接触,像斐波那契序列的求解等这些都是可以用递归来解决的。java方法是支持嵌套调用方法不支持嵌套定义。

       使用递归需要注意以下几点:1 递归需要一个基值情况,其意思是导致递归的返回而没有再一次递归调用。2 第一个递归都需要有终止条件。以防止无限递归下去,可能由此引发程序崩溃。以上两点是在递归调用中特别需要注意的两个环节。

      使用的递归的情况很多,比如说数学归纳法,数列求和等。接下来使用递归实现单词的全排列。任意给一个单词,输出所有该单词的字母组合。例如输入一个单词有5个字符,那么全排列一共有5*4*3*2*1=120种排列组合。这个可以用递归来实现。

      通常如果按照比较直接的想法就是采用分步乘法原理来实现单词全排列。采用for循环方式:例如用户输入四个字符长度的单词,输出所有该单词的字符全排列组合。

public class WholeShowWordNotRecursiveApp {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        WholeShowWorldNotRecursive a=new WholeShowWorldNotRecursive();

    }

}
class WholeShowWorldNotRecursive
{
    //不采用递归的方法对单词进行全排列
    private char[] arr=new char[100];
    private int size=0;
    private String s="";
    public WholeShowWorldNotRecursive()
    {
        String s=getString();
        size=s.length();
        //将输入单词各个字符存放在char数组中
        for(int i=0;i<size;i++)
        {
            arr[i]=s.charAt(i);
        }
        this.wholeArr(size);
    }
    //全排序方法 采用比较直接的排序方式 假设5个字符 一共应该有5*4*3*2*1=120种情况 这里可以给出单词字母个数是3的示例,实际上给出不定长度的单词全排列时不用递归比较难实现
    public void wholeArr(int wordSize)
    {
        String temp="";
      for(int i=0;i<wordSize;i++)
      {
          for(int j=0;j<wordSize;j++)
          {
              for(int k=0;k<wordSize;k++)
              {
                  if(i!=j&&i!=k&&j!=k)
                  {
                      temp=arr[i]+""+arr[j]+""+arr[k]+"";
                      System.out.println(temp);
                  }
              }
          }
      }
    }
  //获取用户由键盘输入字符串
    public  String getString() 
    {
        System.out.println("请输如一个单词:");
        InputStreamReader isr=new InputStreamReader(System.in);
        BufferedReader br=new BufferedReader(isr);
        try 
        {
            s=br.readLine();
        } catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally
        {

            try 
            {
                 br.close();
                 isr.close();
            } catch (IOException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }   
        return s;   
    }
}

用户可以输入dsa,则结果显示该单词全排列为:

dsa
das
sda
sad
ads
asd

      以上代码虽然能够实现单词全排列,但是面对无法确定长度的单词来说就显得比较麻烦,或者虽然采用多级for循环实现全排列,但效率并不高。采用递归的解决思路如下:

假设这个单词有n个字符,可执行一下步骤:

1 全排列最后边n-1个字母

2 轮换所有n个字符

3 重复以上步骤n次

      轮换的意思是所有的字母向左移一位,最左边字符保持不变,会转换到最右边字母的后边。以上步骤可以用下图表示:

这里写图片描述

      以上做法可以使每一个字符都可以移动到第一个。这个过程的可以由以下代码表示:

public static void fullArray(int newSize)
    {
        if(newSize==1)//此处是终止递归的条件
            return;
        for(int i=0;i<newSize;i++)
        {
            //相当于三层for循环 可以使用非递归的方法实现该单词全排列
            fullArray(newSize-1);
            if(newSize==2)
            {
                //显示单词
                showWorld();
            }
            //倒转单词
            rotate(newSize);
        }

    }
    //旋转单词
    public static void rotate(int newsize)
    {
        int j=0;
        int position=size-newsize;
        char temp=arr[position];
        for(j=position+1;j<size;j++)
        {
            arr[j-1]=arr[j];//n-1个字符都向左移动
        }
        arr[j-1]=temp;//最左边字符移动到最右边
    }

    //显示单词
    public static void showWorld()
    {
        if(count<99)
        {
            System.out.print(" ");
        }
        if(count<9)
            System.out.print("");
        System.out.print(++count+" ");
        for(int j=0;j<size;j++)
        {
            System.out.print(arr[j]);
            System.out.print("");
            System.out.flush(); 
        }
        System.out.print(" ");
        if(count%6==0)
        {
            System.out.println("");
        }
    }

用户输入tw,全排列为: 1 tw 2 wt

用户输入dsa ,全排列为:1 dsa 2 das 3 sad 4 sda 5 ads 6 asd

用户输入word ,全排列为:

1 word 2 wodr 3 wrdo 4 wrod 5 wdor 6 wdro

7 ordw 8 orwd 9 odwr 10 odrw 11 owrd 12 owdr

13 rdwo 14 rdow 15 rwod 16 rwdo 17 rodw 18 rowd

19 dwor 20 dwro 21 dorw 22 dowr 23 drwo 24 drow

      很明显使用递归能够减少代码量,还可以处理任意长度的单词进行全排列。这样的确比上面的for循环灵活。

归于递归的效率

      递归虽然在使用中比直接去实现代码功能的要灵活,看起来能够减少代码篇幅,但是在递归过程中会产生栈的额外开销,包括方法地址的返回以及方法参数都要返回到一个内部的栈里面。这与while循环方法执行的速度可能要慢一些,如果递归中需要压栈的参数和地址返回过多就会形成栈溢出现象,不过递归可以简化问题,对于效率递归不是很突出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值