自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

打印從1到最大的n位數(shù)

開發(fā) 測試
有一個(gè)數(shù)字n,我們需要按照順序輸出從1到最大的n位十進(jìn)制數(shù),例如:n = 3,則輸出1、2、3...一直到最大的3位數(shù)999。

本文轉(zhuǎn)載自微信公眾號「神奇的程序員」,作者神奇的程序員。轉(zhuǎn)載本文請聯(lián)系神奇的程序員公眾號。

前言

有一個(gè)數(shù)字n,我們需要按照順序輸出從1到最大的n位十進(jìn)制數(shù),例如:n = 3,則輸出1、2、3...一直到最大的3位數(shù)999。

本文將將帶著大家一起解決這個(gè)問題,分析解決思路與實(shí)現(xiàn)方法,歡迎各位感興趣的開發(fā)者閱讀本文。

循環(huán)解法

當(dāng)我們過一眼這個(gè)問題后,腦海中想到的第一個(gè)思路肯定是:

  • 先求出這個(gè)最大的n位數(shù)
  • 用一個(gè)循環(huán)從1開始逐個(gè)打印至最大的n位數(shù)

很輕松就能寫出如下所示的代碼:

export default class PrintMaxNumber {
// 通過遍歷獲取最大值
public traverseForMax(n: number): void {
let maxNumber = 1;
let i = 0;
while (i++ < n) {
// 每次對結(jié)果*10,得出最小的n+1位的值
maxNumber *= 10;
}
// 輸出1到最大值-1位置的值,就是n位數(shù)的最大值
for (let i = 1; i < maxNumber; i++) {
console.log(i);
}
}
}

這段代碼乍一看沒啥問題,當(dāng)n = 3的時(shí)候可以正常輸出1~999之間的所有值,但是題目中n并沒有規(guī)定具體范圍,當(dāng)n很大的時(shí)候,超出了js可以表示的最大范圍,代碼將無法運(yùn)行。

排列解法

上述思路無法解決大數(shù)問題,接下來我們換一種思路來考慮這個(gè)問題。如果我們在數(shù)字前面補(bǔ)0,就會發(fā)現(xiàn)n位所有十進(jìn)制數(shù)其實(shí)就是n個(gè)從0~9的全排列。也就是說,只要我們把數(shù)字的每一位都從0~9排列一遍,就得到了所有的十進(jìn)制數(shù)。

全排列使用遞歸的方式很容易表達(dá),數(shù)字的每一位都只可能是0~9中的一個(gè)數(shù),然后設(shè)置下一位。遞歸結(jié)束的條件就是我們已經(jīng)設(shè)置了數(shù)字的最后一位。

注意:對遞歸不了解的開發(fā)者,請移步我的另一篇文章:遞歸的理解與實(shí)現(xiàn)[1]

接下來,我們來看下實(shí)現(xiàn)思路:

  • 準(zhǔn)備一個(gè)數(shù)組用于描述數(shù)字的所有位數(shù)
  • 從0遍歷至9,進(jìn)入循環(huán)
  • 填充數(shù)字的最高位,即數(shù)組的0號元素
  • 調(diào)用遞歸函數(shù),填充數(shù)組其他位置的元素,即除最大位外的其他位
  • 遞歸函數(shù)的實(shí)現(xiàn)
  • 計(jì)算下一位,填充數(shù)組下一位的值。
  • 繼續(xù)執(zhí)行遞歸函數(shù)
  • 接受三個(gè)參數(shù):數(shù)字位數(shù)組、數(shù)字的總位數(shù)、當(dāng)前位
  • 基線條件:當(dāng)前位是最大位的前一位
  • 從0遍歷至9,進(jìn)入循環(huán):

我們舉個(gè)例子,通過一個(gè)圖來描述下上述思路的執(zhí)行過程,我們用n來描述所求位數(shù),當(dāng)n=3時(shí),那么遞歸樹就如下所示:

  • A控制百位,使用遞歸從0排列至9
  • B控制十位與個(gè)位,使用遞歸從0排列至9

注意:A中的遍歷永遠(yuǎn)只關(guān)注最高位數(shù)字的排列賦值,B中的遍歷關(guān)注其它位數(shù)字的排列賦值。當(dāng)執(zhí)行棧中的B執(zhí)行完時(shí),則代表其他位已經(jīng)排列到了9。此時(shí)A中的遍歷就會繼續(xù)執(zhí)行,修改最高位的值。重復(fù)上述流程,直至A中的遍歷結(jié)束,所有的數(shù)字也就排列完成了。

提取正確的數(shù)字

當(dāng)遞歸的基線條件滿足時(shí),我們就需要將當(dāng)前數(shù)字位數(shù)組中的值打印出來,我們在存儲的時(shí)候給每一位數(shù)字的后面加多了一個(gè)0,我們打印時(shí)需要進(jìn)一步處理,取出有效值即可,實(shí)現(xiàn)思路如下:

  • 通過遍歷,取出數(shù)組中每一項(xiàng)字符串的第0號元素
  • 從取出的字符串中,從最高位開始遍歷找到第一個(gè)非0數(shù),將其存起來
  • 最后,輸出存儲的值即可。

實(shí)現(xiàn)代碼

思路有了,理論也可行,那么代碼就能輕松寫出來了,如下所示:

export default class PrintMaxNumber {
public maxNumberToStr(n: number): void {
if (n <= 0) return;
const numberStr: string[] = [];
// 控制數(shù)字最高位的排列(0 ~ 9)
for (let i = 0; i < 10; i++) {
numberStr[0] = i + "0";
this.printToMaxRecursively(numberStr, n, 0);
}
}

/**
* 遞歸獲取最大值
* @param numStr 數(shù)字位數(shù)組
* @param length 數(shù)字位數(shù)
* @param index 當(dāng)前位
* @private
*/
private printToMaxRecursively(
numStr: string[],
length: number,
index: number
): void {
if (index === length - 1) {
// 打印
PrintMaxNumber.printNumber(numStr);
return;
}
// 控制數(shù)字其他位的排列(0 ~ 9
for (let i = 0; i < 10; i++) {
const nextIndex = index + 1;
numStr[nextIndex] = i + "0";
this.printToMaxRecursively(numStr, length, nextIndex);
}
}

/**
* 輸出數(shù)字位數(shù)組中的有效數(shù)字
* @param numStr
* @private
*/
private static printNumber(numStr: string[]): void {
const nLength = numStr.length;
let remove0Val = "";

// 篩選除去多余0后的值
// 假設(shè)此時(shí)的值是3位數(shù),那么對應(yīng)的數(shù)組就為["00","00","10"], 數(shù)組每一項(xiàng)值的第0位才是我們需要的值
for (let i = 0; i < nLength; i++) {
const strVal = numStr[i];
// 取數(shù)組每一項(xiàng)的第0位
remove0Val += strVal[0];
}

let finalVal = "";
// 是否從0開始
let isBeginning0 = true;
// 篩選出第一個(gè)非0值的字符索引
for (let i = 0; i < remove0Val.length; i++) {
// 從0開始的狀態(tài)為true且當(dāng)前字符不為0
if (isBeginning0 && remove0Val[i] !== "0") {
// 表示我們已找到第一個(gè)非0數(shù),修改狀態(tài)
isBeginning0 = false;
}

// 當(dāng)前位的數(shù)非0,將其存起來
if (!isBeginning0) {
finalVal += remove0Val[i];
}
}
if (finalVal !== "") {
console.log(finalVal);
}
}
}

測試用例

接下來,我們來測試下當(dāng)n = 3時(shí),上述代碼能否正常運(yùn)行。

import PrintMaxNumber from "../PrintMaxNumber.ts";

const printNumber = new PrintMaxNumber();
printNumber.maxNumberToStr(3);

運(yùn)行結(jié)果如下所示,符合預(yù)期。

image-20220209011016743

示例代碼

本文所列舉的完整示例代碼請移步:

  • PrintMaxNumber.ts[2]
  • printMaxNumber-test.ts[3]

寫在最后

至此,文章就分享完畢了。

我是神奇的程序員,一位前端開發(fā)工程師。

參考資料

[1]遞歸的理解與實(shí)現(xiàn): https://juejin.cn/post/6844904197612109838

[2]PrintMaxNumber.ts: https://github.com/likaia/algorithm-practice/blob/3e998c85e40f37101e8d47a5eb5a97eb88e6a21d/src/PrintMaxNumber.ts

[3]printMaxNumber-test.ts: https://github.com/likaia/algorithm-practice/blob/3e998c85e40f37101e8d47a5eb5a97eb88e6a21d/src/test-case/printMaxNumber-test.ts

[4]個(gè)人網(wǎng)站: https://www.kaisir.cn/


責(zé)任編輯:武曉燕 來源: 神奇的程序員
相關(guān)推薦

2022-05-09 08:35:43

面試產(chǎn)品互聯(lián)網(wǎng)

2018-04-11 16:52:44

2017-11-01 17:27:18

數(shù)據(jù)中心

2018-07-30 09:00:49

技術(shù)管理實(shí)踐

2019-09-09 16:33:10

華為

2021-06-29 17:20:16

數(shù)據(jù)中臺用友iuap

2023-05-29 15:20:21

5G工業(yè)互聯(lián)網(wǎng)

2016-11-28 16:23:23

戴爾

2021-05-28 09:01:34

5G5G網(wǎng)絡(luò)5G終端

2020-04-14 10:38:33

華為服務(wù)政企

2018-09-28 16:01:38

SLCQLCSSD

2023-04-17 18:50:03

2016-06-16 19:21:59

阿里云云服務(wù)器資源編排

2023-03-22 11:41:56

2023-03-19 17:36:38

2023-05-31 15:47:52

銳捷

2022-06-21 10:10:14

HTTP協(xié)議TCP

2021-07-01 07:03:32

開發(fā)Webpack代碼

2021-03-10 09:21:00

Spring開源框架Spring基礎(chǔ)知識
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號