简介
之前阿里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的问题,因为要压栈。
- 先写循环,再写递归会快一些。循环相当于正向思维;递归偏向逆向思维;
- 代码这里以实现算法为主,很多地方还可以再做优化