阶梯树求和

Posted on By Vivian Sun

简介

之前阿里4面遇到一个算法题:阶梯树求和

题目说明

阶梯树是:12,10,123,121….. 规律是每个数字的前后都比它自己多1或少1

给定一个值10,000,求出10,000以内所有阶梯树的总和

实现

面试手写code的时候,面试官有提醒n位阶梯树是n-1为阶梯树向右扩展(见过最和蔼可亲的面试官了O(∩_∩)O哈哈~)

核心的思想有两点:

  • 每个数字前后都比它加1 or 减1, 从组合上来说就是C21
  • n位的阶梯树是n-1位的阶梯树向右扩展

现场没有写好,回来后仔细思量下,用循环和递归两种方式实现了下。

代码如下:

package com.wenxi.learn.algorithm.algothrim;

import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 阶梯树求和算法
 * 阶梯树 12, 10, 121,123等。数字的左右两边都大1或小一; 是大于等于0的数值
 * 规律:
 * 1. i(i+1)i(i-1)
 * 2. n位的阶梯树是n-1位向有扩展;(向左扩展会重复)
 */
public enum JieTiTree {
    INSTANCE;

    private final static String TAG = "JieTiTree";
    private final static int MAX_NUM = 10000;
    private final static int BIT_NUM = String.valueOf(MAX_NUM).length();

    public void start() {
        new WhileTest().strategyWhile();
        new RecursiveTest().strategyRecursive();
    }

    class RecursiveTest {
        int sum = 0;
        List<Integer> array = new ArrayList<>();
        List<Integer> array_temp = new ArrayList<>();
        String temp_str;
        int temp_int;
        int last_num;
        int num1, num2; // i+1; i-1

        public void strategyRecursive() {
            // tag start time
            long startTime = System.nanoTime();
            recursiveLoop(2);
            Log.d(TAG, "strategyRecursive sum = " + sum);
            // tag end time
            long diffMs = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
            Log.d(TAG, "strategyRecursive time diff = " + diffMs + "ms");
        }

        private void recursiveLoop(int index) {
            if (index == 2) {
                for (int n = 1; n < 10; n++) {
                    // calculator +1, -1
                    temp_int = n * 10;
                    // add to sum
                    if (n + 1 < 10) {
                        sum += temp_int + n + 1;
                        array.add(temp_int + n + 1);
                        //Log.d(TAG, "index = " + index + "; num = " + (temp_int + n + 1));
                    }
                    sum += temp_int + n - 1;
                    array.add(temp_int + n - 1);
                    //Log.d(TAG, "index = " + index + "; num = " + (temp_int + n - 1));
                }
                recursiveLoop(index + 1);
            } else {
                // create temp array to for circle
                array_temp.clear();
                for (int s = 0; s < array.size(); s++) {
                    temp_str = String.valueOf(array.get(s));
                    temp_str = temp_str.substring(temp_str.length() - 1);
                    last_num = Integer.parseInt(temp_str);
                    num1 = last_num + 1;
                    num2 = last_num - 1;
                    temp_int = array.get(s) * 10;
                    // add to sum
                    if (num1 < 10) {
                        sum += temp_int + num1;
                        array_temp.add(temp_int + num1);
                        //Log.d(TAG, "index = " + index + "; num = " + (temp_int + num1));
                    }
                    if (num2 > 0) {
                        sum += temp_int + num2;
                        array_temp.add(temp_int + num2);
                        //Log.d(TAG, "index = " + index + "; num = " + (temp_int + num2));
                    }
                }
                array.clear();
                array.addAll(array_temp);

                if (index != BIT_NUM - 1) {
                    recursiveLoop(index + 1);
                }
            }
        }

        public int getSum() {
            return sum;
        }
    }

    class WhileTest {
        int sum = 0;

        private void strategyWhile() {
            // tag start time
            long startTime = System.nanoTime();
            whileLoop();
            Log.d(TAG, "strategyWhile sum = " + sum);
            // tag end time
            long diffMs = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
            Log.d(TAG, "strategyWhile time diff = " + diffMs + "ms");
        }

        private void whileLoop() {
            int index = 2;
            int num1, num2; // i+1; i-1
            int last_num;
            List<Integer> array = new ArrayList<>();
            List<Integer> array_temp = new ArrayList<>();
            String temp_str;
            int temp_int;
            while (index < BIT_NUM) {
                // 2 bits num, such as 12,10
                if (index == 2) {
                    for (int n = 1; n < 10; n++) {
                        // calculator +1, -1
                        num1 = n + 1;
                        num2 = n - 1;
                        temp_int = n * 10;
                        // add to sum
                        if (num1 < 10) {
                            sum += temp_int + num1;
                            array.add(temp_int + num1);
                            //Log.d(TAG, "index = " + index + "; num = " + (temp_int + num1));
                        }
                        sum += temp_int + num2;
                        array.add(temp_int + num2);
                        //Log.d(TAG, "index = " + index + "; num = " + (temp_int + num2));
                    }
                } else {
                    // create temp array to for circle
                    array_temp.clear();
                    for (int s = 0; s < array.size(); s++) {
                        temp_str = String.valueOf(array.get(s));
                        temp_str = temp_str.substring(temp_str.length() - 1);
                        last_num = Integer.parseInt(temp_str);
                        num1 = last_num + 1;
                        num2 = last_num - 1;
                        temp_int = array.get(s) * 10;
                        // add to sum
                        if (num1 < 10) {
                            sum += temp_int + num1;
                            array_temp.add(temp_int + num1);
                            //Log.d(TAG, "index = " + index + "; num = " + (temp_int + num1));
                        }
                        if (num2 > 0) {
                            sum += temp_int + num2;
                            array_temp.add(temp_int + num2);
                            //Log.d(TAG, "index = " + index + "; num = " + (temp_int + num2));
                        }
                    }
                    array.clear();
                    array.addAll(array_temp);

                }// end else

                index++;
            }// end while
        }

        public int getSum() {
            return sum;
        }
    }

}

完成源码Github在这里

备注:

  • 递归比循环快,但是递归要小心stack的问题,因为要压栈。
  • 先写循环,再写递归会快一些。循环相当于正向思维;递归偏向逆向思维;
  • 代码这里以实现算法为主,很多地方还可以再做优化