2.TDD实现字符串排列组合

  题目地址:http://cyber-dojo.org/setup_default_start_point/show/?from=individual , 第二题。题目如下:
Write a program to generate all potential anagrams of an input string.For example, the potential anagrams of “biro” are
biro bior brio broi boir bori
ibro ibor irbo irob iobr iorb
rbio rboi ribo riob roib robi
obir obri oibr oirb orbi orib
  说白了就是给定一个字符串进行排列组合。咋一看确实很难做,有点难度。**这里我们一步步剖析TDD的实现。让你清清楚楚明白TDD。**TDD实现这个题目是水到渠成的。
  
一、TDD之前我们先建立两个类:test和要解决上述问题的答案代码
  我们先建立测试类,也建立调用的方法。
  
测试类AnagramsTest框架:

public class AnagramsTest {
    @Test
    public void testOnlyOneLetter() {
        //given

        //when

        //then
    }
}

业务类AnagramsProblem 框架:

public class AnagramsProblem {
    public List<String> getAnagrams(String givenString) {
        return null;
    }
}

二、当只有一个字母的时候
  当传入的字符串只有一个字符时,代码如下:
测试类:

public class AnagramsProblemTest {
    @Test
    public void testOnlyOneLetter() {
        //given(入参)
        String strGiven = "b";
        //引用anagramsProblem指向新AnagramsProblem对象,使用引用调用 排列组合 的实现方法
        AnagramsProblem anagramsProblem = new AnagramsProblem();

        //when(调用方法)
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);

        //then(验证)
        Assert.assertEquals(Arrays.asList("b"), strReturn);
    }
}

业务类:

public class AnagramsProblem {
    public List<String> getAnagrams(String givenString) {
        List<String> strList = new ArrayList<>();//java 1.8 新特性
        strList.add(givenString);
        return strList;
    }
}

  运行测试代码,成功,说明返回值跟预期的一样。
这里写图片描述

三、当有两个字母的时候
测试类:

public class AnagramsProblemTest {
    @Test
    public void testOnlyOneLetter() {
        //given(入参)
        String strGiven = "b";
        AnagramsProblem anagramsProblem = new AnagramsProblem();

        //when(调用方法)
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);

        //then(验证)
        Assert.assertEquals(Arrays.asList("b"), strReturn);
    }

    @Test
    public void testTwoLetters() {
        //given
        String strGiven = "bi";
        AnagramsProblem anagramsProblem = new AnagramsProblem();

        //when
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);

        //then
        Assert.assertEquals(Arrays.asList("bi", "ib"), strReturn);
    }
}

业务类:

public class AnagramsProblem {
    public List<String> getAnagrams(String givenString) {
        List<String> strList = new ArrayList<>();//java 1.8 新特性
        if(givenString.length() == 1) {
            strList.add(givenString);
            return strList;
        }

        if(givenString.length() == 2) {
            strList.add("" + givenString.charAt(0) + givenString.charAt(1));
            strList.add("" + givenString.charAt(1) + givenString.charAt(0));
            return strList;
        }
        return null;
    }
}

三、当有三个字母的时候
测试类:

package cs.anagrams;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;

public class AnagramsProblemTest {
    @Test
    public void testOnlyOneLetter() {
        //given(入参)
        String strGiven = "b";
        AnagramsProblem anagramsProblem = new AnagramsProblem();

        //when(调用方法)
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);

        //then(验证)
        Assert.assertEquals(Arrays.asList("b"), strReturn);
    }

    @Test
    public void testTwoLetters() {
        //given
        String strGiven = "bi";
        AnagramsProblem anagramsProblem = new AnagramsProblem();

        //when
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);

        //then
        Assert.assertEquals(Arrays.asList("bi", "ib"), strReturn);
    }

    @Test
    public void testThreeLetters() {
        //given
        String strGiven = "bir";
        AnagramsProblem anagramsProblem = new AnagramsProblem();
        /** 这里需要排序,不然他会按顺序比较指定位置的字符串,可能会出错    */
        List<String> strExpect = Arrays.asList("bir", "bri", "ibr", "irb", "rbi", "rib");
        Collections.sort(strExpect);

        //when
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
        Collections.sort(strReturn);

        //then
        Assert.assertEquals(strExpect, strReturn);
    }
}

业务类:

package cs.anagrams;

import java.util.ArrayList;
import java.util.List;

public class AnagramsProblem {
    public List<String> getAnagrams(String givenString) {
        List<String> strList = new ArrayList<>();//java 1.8 新特性
        if(givenString.length() == 1) {
            strList.add(givenString);
            return strList;
        }

        if(givenString.length() == 2) {
            //重复代码
            strList.add("" + givenString.charAt(0) + givenString.charAt(1));
            strList.add("" + givenString.charAt(1) + givenString.charAt(0));
            return strList;
        }

        if(givenString.length() == 3) {
            //重复代码
            strList.add("" + givenString.charAt(0) + givenString.charAt(1) + givenString.charAt(2));
            strList.add("" + givenString.charAt(0) + givenString.charAt(2) + givenString.charAt(1));
            strList.add("" + givenString.charAt(1) + givenString.charAt(0) + givenString.charAt(2));
            strList.add("" + givenString.charAt(1) + givenString.charAt(2) + givenString.charAt(0));
            strList.add("" + givenString.charAt(2) + givenString.charAt(0) + givenString.charAt(1));
            strList.add("" + givenString.charAt(2) + givenString.charAt(1) + givenString.charAt(0));
            return strList;
        }
        return null;
    }
}

  找规律:

if(givenString.length() == 3) {
            String str = givenString.replace(givenString.charAt(0) + "", "");
            strList.add("" + givenString.charAt(0) + givenString.charAt(1) + givenString.charAt(2));
            strList.add("" + givenString.charAt(0) + givenString.charAt(2) + givenString.charAt(1));

            String str1 = givenString.replace(givenString.charAt(1) + "", "");
            strList.add("" + givenString.charAt(1) + givenString.charAt(0) + givenString.charAt(2));
            strList.add("" + givenString.charAt(1) + givenString.charAt(2) + givenString.charAt(0));

            String str2 = givenString.replace(givenString.charAt(2) + "", "");
            strList.add("" + givenString.charAt(2) + givenString.charAt(0) + givenString.charAt(1));
            strList.add("" + givenString.charAt(2) + givenString.charAt(1) + givenString.charAt(0));
            return strList;
        }

  重构代码:

if(givenString.length() == 3) {
     for (int i = 0; i < givenString.length(); i++) {
         String str = givenString.replace(givenString.charAt(i) + "", "");
         strList.add("" + givenString.charAt(i) + str.charAt(0) + str.charAt(1));
         strList.add("" + givenString.charAt(i) + str.charAt(1) + str.charAt(0));

     }
     return strList;
 }

  查找规律:

if(givenString.length() == 3) {
   for (int i = 0; i < givenString.length(); i++) {
       String str = givenString.replace(givenString.charAt(i) + "", "");
       strList.add("" + givenString.charAt(i) + getAnagrams(str).get(0));
       strList.add("" + givenString.charAt(i) + getAnagrams(str).get(1));
   }
   return strList;
}

  再次重构givenString.length() == 3的代码,去掉重复代码,抽方法,inline代码:

if(givenString.length() == 3) {
    for (int i = 0; i < givenString.length(); i++) {
        for (int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++) {
            strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
        }
    }
    return strList;
}

  最终如下:

package cs.anagrams;

import java.util.ArrayList;
import java.util.List;

public class AnagramsProblem {
    public List<String> getAnagrams(String givenString) {
        List<String> strList = new ArrayList<>();//java 1.8 新特性
        if(givenString.length() == 1) {
            strList.add(givenString);
            return strList;
        }

        if(givenString.length() == 2) {
            strList.add("" + givenString.charAt(0) + givenString.charAt(1));
            strList.add("" + givenString.charAt(1) + givenString.charAt(0));
            return strList;
        }

        if(givenString.length() == 3) {
            for (int i = 0; i < givenString.length(); i++) {
                for (int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++) {
                    strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
                }
            }
            return strList;
        }
        return null;
    }

    private String getRemaindString(String givenString, int i) {
        return givenString.replace(givenString.charAt(i) + "", "");
    }
}

四、当有四个字母的时候
测试方法:

@Test
    public void testFourLetters() {
        //given
        String strGiven = "biro";
        AnagramsProblem anagramsProblem = new AnagramsProblem();
        List<String> exceptStr = Arrays.asList("biro", "bior", "brio", "broi", "boir", "bori",
            "ibro", "ibor", "irbo", "irob", "iobr", "iorb",
            "rbio", "rboi", "ribo", "riob", "roib", "robi",
            "obir", "obri", "oibr", "oirb", "orbi", "orib");
        Collections.sort(exceptStr);

        //when
        List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
        Collections.sort(strReturn);

        //then
        Assert.assertEquals(exceptStr, strReturn);
    }

业务语句:

if(givenString.length() == 4) {
    for (int i = 0; i < givenString.length(); i++) {
         for (int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++) {
             strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
         }
     }
     return strList;
 }

五、当有N个字母的时候
业务类,抽共性:

package cs.anagrams;

import java.util.ArrayList;
import java.util.List;

public class AnagramsProblem {
    public List<String> getAnagrams(String givenString) {
        List<String> strList = new ArrayList<>();//java 1.8 新特性
        if(givenString.length() == 1) {
            strList.add(givenString);
            return strList;
        }

        if(givenString.length() >= 2) {
            for (int i = 0; i < givenString.length(); i++) {
                for(int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++)
                strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
            }
            return strList;
        }

        return null;
    }

    private String getRemaindString(String givenString, int i) {
        return givenString.replace(givenString.charAt(i) + "", "");
    }
}

六、去掉重复字符
  使用set代替List即可

猜你喜欢

转载自blog.csdn.net/u010986518/article/details/82420786