曾经我被鄙视的笔试题,虽然不难,但还是有点内容的,不管用什么语言,大家都可以来试试

203 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

今天晚上回来闲来无事,想写写代码换换思路,于是就想到了N年前的一道面试题(很遗憾当年没有做出来,导致自己的笔试被鄙视了),写个java方法实现针对原始长度为N的字符串,使用0-N个代替原始字母后的所有结果,举个栗子:给定字符串为ABC,则需要输出ABC,AB*,A*C,A**,*BC,B,C,(结果应该是2的N次方个)。没多想就它了,哪里跌倒哪里爬起来,大家如果感兴趣也来试一试,限时15分钟,权当脑筋急转弯了。

思路

如果已经有思路且开始去实现的小伙伴们就不用往下看了,直接运行输出结果就行了。

如果还没有思路,我提供一个思路,然后大家试着去实现一下:

从题面分析就是给定条件输出各种组合,回到这道题,其实更形象的描述应该是二进制加法,想象一下像不像?000,001,010,011,100,101,110,111(当初怎么没有这个灵感....)

实现逻辑

既然想明白了就开始撸代码吧,作者使用的是java,大家可以使用其他语言,如果有的语言有类似的api功能,那还是别直接用了,那样就没乐趣了。废话不多说,直接上代码:

public class Test {
 
  public static void main(String[] args) {
    List<String> list = Arrays.asList(new String[]{"A""B""C""D"});
    printStarComposition(list);
  }
 
  private static void printStarComposition(List<String> list) {
    int[] array = new int[list.size()];
    StringBuffer sb = new StringBuffer();
    while (true) {
      //1打印*,0打印原始值
      for (int i = 0; i < array.length; i++) {
        if (array[i] == 1) {
          sb.append("*");
        } else {
          sb.append(list.get(i));
        }
      }
      //打印拼接字符串
      System.out.println(sb.toString());
      //对象重用,删除当前值
      sb.delete(0, sb.length());
      //标识是否需要执行加法,每轮执行一次
      boolean needAdd = true;
      //核心算法类似二进制加法,就是反向遍历整形数组,如果遇到1,则将1变成0,遇到第一个0,变成1,然后跳出for循环
      for (int i = array.length - 1; i >= 0; i--) {
        if (array[i] == 0) {
          array[i]++;
          needAdd = false;
          break;
        } else {
          array[i] = 0;
        }
      }
      //如果循环退出后needAdd仍旧是true,说明未遇到0,数组中都是1,说明打印完毕,跳出死循环,打印结束
      if (needAdd) {
        break;
      }
    }
  }
}

执行结果如下:

ABCD
ABC*
AB*D
AB**
A*CD
A*C*
A**D
A***
*BCD
*BC*
*B*D
*B**
**CD
**C*
***D
****

结语

条条大路通罗马,编程也是,差的就是这条路的远近(执行效率以及代码质量),但是找到近路的前提是先要找到路。当初我就没有找到路,结果连罗马长什么样子都不知道....

不过塞翁失马焉知非福,如果当初真的到了罗马,现在的我会是什么样子,一切未知。但是有一点可知的是,如果你是技术人员或者曾经是技术人员,任何时候都不要放弃技术,这是一个技术人员安身立命的本钱,如果你还在软件圈哪怕你转行,技术也会成为你一个非对称打击的优势点,能成为你剩余职业生涯中的一把利器。

技术好比你的肌肉,哪怕你已经不去健身房了,仍需要时不时的锻炼来维护肌肉状态,这样肌肉才不会变成五花肉,技术亦是如此。